1 DAY 1:2月20日

1.1 RStudio で Project の作成

1.1.1 確認

  1. R と R Studio のインストール
  2. RStudio: New Project 作成
  • R Studio の起動
  • New Project: eco232, eco232.Rproj
  1. Save して、終了
  2. プロジェクトを起動確認

1.2 基本コマンド - in Console

  • head(cars)
  • str(cars)
  • summary(cars)
  • df_cars <- cars
    • <-_%>% と ` back tick の確認
  • View(cars) または、右上の Environment から、df_cars をクリック
  • ?cars または Help 検索窓で cars, head など

おすすめ:Sys.setenv(LANG = "en")

1.3 Package の確認とインストール

R packages are extensions to the R statistical programming language containing code, data, and documentation in a standardised collection format that can be installed by users of R using Tool > Install Packages in the top menu bar of R Studio.

Rパッケージは、Rの拡張機能で、コード、データ、ドキュメントを標準化されたコレクション形式で含んでおり、標準的なものは、R Studio の Top Bar の Tool > Install Packages からインストールできます。

  • Minimum: tidyverse, rmarkdown, WDI

あとから使うので、ロードしておきます。最初に次のようなコードを実行します。右の三角を押します。

library(tidyverse)
library(WDI)

1.4 R Markdown 入門

1.4.1 R Notebook

R Markdownはデータサイエンスのためのオーサリングフレームワーク。

コード(プログラム)とその実行結果、を記録・表示し、高品質のレポートの作成を可能にします。

R Notebook は、独立してインタラクティブに実行できるチャンクを持つR Markdownドキュメントの一つの形式で、入力のすぐ下に出力が表示することができます。

  1. File > New File > R Notebook
  2. Save with a file name, say, test-notebook
  3. Preview by [Preview] button
  4. Run Code Chunk plot(cars) and then Preview again.

1.5 World Development Indicator (WDI)

WDI(country = "all", indicator = c(gdp = "NY.GDP.MKTP.CD"),
    extra=TRUE, cache=wdi_cache) %>% drop_na(gdp) %>%
  filter(year==max(year), income !="Aggregates") %>% 
  drop_na(region) %>% arrange(desc(gdp))
chosen_countries <- c("United States","China", "Japan", "Germany", "United Kingdom","India")
WDI(country = c("CN","GB","JP","IN","US","DE"), indicator = c(gdp = "NY.GDP.MKTP.CD"), extra=TRUE) %>% drop_na(gdp) %>% 
  ggplot(aes(year, gdp, col = country)) + geom_line() +
  labs(title = "WDI NY.GDP.MKTP.CD: gdp")

WDI(country = c("CN","IN","JP","US"), 
    indicator = c(gdp_growth_rate = "NY.GDP.MKTP.KD.ZG"), extra=TRUE) %>%
  drop_na(gdp_growth_rate) %>% 
  ggplot(aes(year, gdp_growth_rate, col = country)) + geom_line() +
  labs(title = paste("WDI NY.GDP.MKTP.KD.ZG: gdp growth rate"))

1.5.1 指標 Indicators (WDI)

  • NY.GDP.MKTP.CD: GDP (current US$)
  • NY.GDP.MKTP.KD.ZG: GDP growth (annual %)

1.5.2 指標 WDI を探してみよう

The World Development Indicators is a compilation of relevant, high-quality, and internationally comparable statistics about global development and the fight against poverty. The database contains 1,400 time series indicators for 217 economies and more than 40 country groups, with data for many indicators going back more than 50 years.

WDIは、世界の開発状況と、貧困との戦いに関する、適切で上質、かつ、国際的に比較可能な時系列の統計データを編纂したものです。このデータベースは、217の経済と40以上の国グループについて1,400の時系列指標を含み、指標のデータの多くは50年以上前に遡ることができます。

1.5.3 指標 WDIの例

  • NY.GDP.MKTP.CD: GDP (current US$)
  • NY.GDP.DEFL.KD.ZG: Inflation, GDP deflator (annual %)
  • SL.UEM.TOTL.NE.ZS: Unemployment, total (% of total labor force) (national estimate)
  • CPTOTNSXN: CPI Price, nominal
  • SL.TLF.CACT.MA.NE.ZS: Labor force participation rate, male (% of male population ages 15+) (national estimate)
  • SL.TLF.CACT.FE.NE.ZS: Labor force participation rate, female (% of male population ages 15+) (national estimate)

1.5.4 練習 1. - 調べてみたい WDI

いくつか、リストしてみましょう。

1.6 WDI パッケージ

WDI パッケージで、データをダウンロードしたり、探したり、詳細情報を得たりできます。

1.6.1 指標 WDI 検索

1.6.1.1 検索例 1(WDI名)

WDIsearch(string = "gdp", field = "name", short = TRUE, cache = NULL)

1.6.1.2 検索例 2(WDI)

WDIsearch(string = "NY.GDP.MKTP.CD", field = "indicator", short = TRUE, cache = NULL)

1.6.1.3 練習 2. - 検索(short)

名前で検索(“” の間に、(なるべく簡単な)検索文字列を入れてください。)

WDIsearch(string = "", field = "name", short = TRUE, cache = NULL)

Indicator で検索(“” の間に、調べたい indicator を入れてください。)

WDIsearch(string = "", field = "indicator", short = TRUE, cache = NULL)

1.6.1.4 詳しい情報を得るには

short = FALSE とします。時間がかかるので、検索は、Indicator と、名前などの情報をもったファイルを手元に持っておくことにします。

wdi_cache <- WDIcache()

右上の窓枠(pane)から、wdi_cache を探して、中身を見てみましょう。series と、country の二つのデータ・フレームからなっているリストです。三角印や、右から二番目の巻物のようなアイコンをクリックすると中身が見えます。

1.6.1.5 検索例 3(WDI名)

WDIsearch(string = "CPI Price", field = "name", short = FALSE, cache = wdi_cache)
  • CPTOTNSXN: CPI Price, nominal
    • The consumer price index reflects the change in prices for the average consumer of a constant basket of consumer goods. Data is not seasonally adjusted.

1.6.1.6 検索例 4(WDI)

WDIsearch(string = "NY.GDP.MKTP.KD.ZG", field = "indicator", short = FALSE, cache = wdi_cache)

1.6.1.7 練習 2 - 検索(long w/ cache)

string と、field を、ふたつとも入れてください。

WDIsearch(string = "", field = "", short = FALSE, cache = wdi_cache)

1.6.2 指標 WDI データのダウンロード

Indicator が決まったら、ダウンロードします。

?WDI

1.6.2.1 ダウンロード例 1-1

df_gdp1 <- WDI(country = "all", indicator = "NY.GDP.MKTP.CD")
df_gdp1

1.6.2.2 ダウンロード例 1-2

df_gdp2 <- WDI(country = "all", indicator = c(gdp = "NY.GDP.MKTP.CD"))
df_gdp2

1.6.2.3 ダウンロード例 1-3

df_gdp3 <- WDI(country = "all", indicator = c(gdp = "NY.GDP.MKTP.CD"), extra=TRUE, cache=wdi_cache)
df_gdp3

1.6.2.4 ダウンロード例 1-4

df_gdp4 <- WDI(country = c("CN","GB","JP","IN","US","DE"), indicator = c(gdp = "NY.GDP.MKTP.CD"), extra=TRUE, cache=wdi_cache)
df_gdp4

1.6.2.5 ダウンロード例 2-1

  • NY.GDP.DEFL.KD.ZG: Inflation, GDP deflator (annual %)
  • CPTOTNSXN: CPI Price, nominal
df_gdp21 <- WDI(country = "all", 
                indicator = c(gdp_deflator = "NY.GDP.DEFL.KD.ZG", 
                              cpi_price = "CPTOTNSXN"), 
                extra=TRUE, cache=wdi_cache)
df_gdp21
str(df_gdp21)
'data.frame':   23972 obs. of  14 variables:
 $ country     : chr  "Advanced Economies" "Advanced Economies" "Advanced Economies" "Advanced Economies" ...
 $ iso2c       : chr  "AME" "AME" "AME" "AME" ...
 $ iso3c       : chr  "" "" "" "" ...
 $ year        : int  1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 ...
 $ status      : chr  "" "" "" "" ...
 $ lastupdated : chr  "2020-07-27" "2020-07-27" "2020-07-27" "2020-07-27" ...
 $ gdp_deflator: num  NA NA NA NA NA NA NA NA NA NA ...
  ..- attr(*, "label")= chr "Inflation, GDP deflator (annual %)"
 $ cpi_price   : num  58.7 60.5 63 66 69.1 ...
  ..- attr(*, "label")= chr "CPI Price,not seas.adj,,,"
 $ region      : chr  NA NA NA NA ...
 $ capital     : chr  NA NA NA NA ...
 $ longitude   : chr  NA NA NA NA ...
 $ latitude    : chr  NA NA NA NA ...
 $ income      : chr  NA NA NA NA ...
 $ lending     : chr  NA NA NA NA ...
summary(df_gdp21)
   country             iso2c              iso3c                year     
 Length:23972       Length:23972       Length:23972       Min.   :1960  
 Class :character   Class :character   Class :character   1st Qu.:1982  
 Mode  :character   Mode  :character   Mode  :character   Median :1996  
                                                          Mean   :1995  
                                                          3rd Qu.:2009  
                                                          Max.   :2021  
                                                                        
    status          lastupdated         gdp_deflator         cpi_price     
 Length:23972       Length:23972       Min.   :  -98.704   Min.   :  0.00  
 Class :character   Class :character   1st Qu.:    2.317   1st Qu.: 55.95  
 Mode  :character   Mode  :character   Median :    5.273   Median : 83.28  
                                       Mean   :   25.308   Mean   : 84.18  
                                       3rd Qu.:   10.411   3rd Qu.:108.75  
                                       Max.   :26765.858   Max.   :551.25  
                                       NA's   :11616       NA's   :18410   
    region            capital           longitude           latitude        
 Length:23972       Length:23972       Length:23972       Length:23972      
 Class :character   Class :character   Class :character   Class :character  
 Mode  :character   Mode  :character   Mode  :character   Mode  :character  
                                                                            
                                                                            
                                                                            
                                                                            
    income            lending         
 Length:23972       Length:23972      
 Class :character   Class :character  
 Mode  :character   Mode  :character  
                                      
                                      
                                      
                                      

右上の窓枠の、Environment も見てみましょう。

1.7 可視化 Visualization

グラフ(Chart)を描いて視覚化しよう

1.7.1 グラフ 1

df_gdp4 %>% ggplot(aes(year, gdp, col=country)) + geom_line()

1.7.2 グラフ 2

df_gdp4 %>% drop_na(gdp) %>% 
  ggplot(aes(year, gdp, col=country)) + geom_line() +
  labs(title = paste("WDI - NY.GDP.MKTP.CD: ", "gdp"))

1.7.3 テンプレート Templates

1.7.3.1 一つの国についての、一つの指標(WDI)と、その略称から、折線グラフを作成

Line Plot with one indicator with abbreviation and one country

chosen_indicator <- "SL.UEM.TOTL.NE.ZS"
short_name <- "unemployment"
chosen_country <- "United States"
WDI(country = "all", indicator = c(short_name = chosen_indicator), extra=TRUE, cache=wdi_cache) %>%
  filter(country == chosen_country) %>% 
  ggplot(aes(year, short_name)) + geom_line() +
  labs(title = paste("WDI ", chosen_indicator, ": ", short_name, " - ", chosen_country),
       y = short_name)

1.7.3.2 一つの国についての、一つの指標(WDI)から、折線グラフを作成

Line Plot with one indicator and one country

chosen_indicator <- "SL.UEM.TOTL.NE.ZS"
chosen_country <- "United States"
WDI(country = "all", indicator = c(chosen_indicator = chosen_indicator), 
    extra=TRUE, cache=wdi_cache) %>%
  filter(country == chosen_country) %>% 
  ggplot(aes(year, chosen_indicator)) + geom_line() +
  labs(title = paste("WDI ", chosen_indicator, " - ", chosen_country), 
       y = chosen_indicator)

1.7.3.3 いくつかの国についての、一つの指標(WDI)と、その略称から、折線グラフを作成

Line Plot with one indicator with abbreviation and several countries

chosen_indicator <- "SL.UEM.TOTL.NE.ZS"
short_name <- "unemployment"
chosen_countries <- c("United States","United Kingdom", "Japan")
WDI(country = "all", indicator = c(short_name = chosen_indicator), extra=TRUE, cache=wdi_cache) %>% drop_na(short_name) %>% 
  filter(country %in% chosen_countries) %>% 
  ggplot(aes(year, short_name, col = country)) + geom_line() +
  labs(title = paste("WDI ", chosen_indicator, ": ", short_name), y = short_name)

1.7.3.4 一つの国についての、二つの指標(WDI)と、その略称から、折線グラフを作成

Line Plot with two indicators with abbreviation and one country

chosen_indicator_1 <- "NY.GDP.DEFL.KD.ZG"
short_name_1 <- "gdp_deflator"
chosen_indicator_2 <- "CPTOTSAXNZGY"
short_name_2 <- "cpi_price"
chosen_country <- "United States"
WDI(country = "all", indicator = c(short_name_1 = chosen_indicator_1, short_name_2 = chosen_indicator_2), extra=TRUE, cache=wdi_cache) %>% 
  filter(country == chosen_country) %>% 
  pivot_longer(c(short_name_1, short_name_2), names_to = "class", values_to = "value") %>% drop_na(value) %>%
  ggplot(aes(year, value, col = class)) + geom_line() +
  labs(title = paste("WDI ", chosen_indicator_1, ": ", short_name_1, "\n", chosen_indicator_2, ": ", short_name_2, " - ", chosen_country)) +
  scale_color_manual(labels = c(short_name_1, short_name_2), values = scales::hue_pal()(2))

chosen_indicator_1 <- "SL.TLF.CACT.MA.NE.ZS"
short_name_1 <- "male"
chosen_indicator_2 <- "SL.TLF.CACT.FE.NE.ZS"
short_name_2 <- "female"
chosen_country <- "United States"
WDI(country = "all", indicator = c(short_name_1 = chosen_indicator_1, short_name_2 = chosen_indicator_2), extra=TRUE, cache=wdi_cache) %>% 
  filter(country == chosen_country) %>% 
  pivot_longer(c(short_name_1, short_name_2), names_to = "class", values_to = "value") %>% drop_na(value) %>%
  ggplot(aes(year, value, col = class)) + geom_line() +
  labs(title = paste("WDI ", chosen_indicator_1, ": ", short_name_1, "\n", chosen_indicator_2, ": ", short_name_2, " - ", chosen_country)) +
  scale_color_manual(labels = c(short_name_1, short_name_2), values = scales::hue_pal()(2))

1.7.3.5 いくつかの国についての、二つの指標(WDI)と、その略称から、折線グラフを作成

Line Plot with two indicators with abbreviation and several countries

chosen_indicator_1 <- "NY.GDP.DEFL.KD.ZG"
short_name_1 <- "gdp_deflator"
chosen_indicator_2 <- "CPTOTSAXNZGY"
short_name_2 <- "cpi_price"
chosen_countries <- c("United States", "France", "Japan")
WDI(country = "all", indicator = c(short_name_1 = chosen_indicator_1, short_name_2 = chosen_indicator_2), extra=TRUE, cache=wdi_cache) %>% 
  filter(country %in% chosen_countries) %>% 
  pivot_longer(c(short_name_1, short_name_2), names_to = "class", values_to = "value") %>% drop_na(value) %>%
  ggplot(aes(year, value, linetype = class, col = country)) + geom_line() +
  labs(title = paste("WDI ", chosen_indicator_1, ": ", short_name_1, "\n", chosen_indicator_2, ": ", short_name_2)) +
  scale_linetype_manual(labels = c(short_name_1, short_name_2), values = c("solid", "dashed"))

chosen_indicator_1 <- "SL.TLF.CACT.MA.NE.ZS"
short_name_1 <- "male"
chosen_indicator_2 <- "SL.TLF.CACT.FE.NE.ZS"
short_name_2 <- "female"
chosen_countries <- c("United States", "France", "Japan")
WDI(country = "all", indicator = c(short_name_1 = chosen_indicator_1, short_name_2 = chosen_indicator_2), extra=TRUE, cache=wdi_cache) %>% 
  filter(country %in% chosen_countries) %>% 
  pivot_longer(c(short_name_1, short_name_2), names_to = "class", values_to = "value") %>% drop_na(value) %>%
  ggplot(aes(year, value, linetype = class, col = country)) + geom_line() +
  labs(title = paste("WDI ", chosen_indicator_1, ": ", short_name_1, "\n", chosen_indicator_2, ": ", short_name_2)) +
  scale_linetype_manual(labels = c(short_name_1, short_name_2), values = c("solid", "dashed"))

1.8 課題 Assignment

上のテンプレートをコピーして、下に貼り付け、指標 indicator と、略称 short_name と、いくつかの国名 chosen_countries を、入れ替えて、試してみてください。

2 DAY 2:2月22日

2.1 探索的データ解析 Exploratory Data Analysis (EDA)

2.1.1 探索的データ解析とは? (Posit Primers)

  1. EDAは、データが何を語っているかを理解するための反復的なサイクルです。

  2. まず、データに関する問いを作成します。

  3. データの可視化、変換、モデリングを行い、答えを探します。

学習したことを活用して、問いを修正したり、新しい問いを考えたりします。そして、このサイクルを繰り返していきます。

EDAはデータ分析において重要な役割を果たします。また、データの品質を保証するために、データの質を確認するために使用することもできます。

R4DS からのイメージ

2.1.2 データの取得・読み込み - Importing Data

スタートは、本来は、データの作成・探索ですが、すでに、分析したいデータはすでにあるとして話を進めます。まずは、data フォルダ(directory)を作成しておくと良い。右下の窓枠の Files タブから、New Folder で作成してもよい。

dir.create("./data")

データの取得・読み込みを、四つの方法に分けて説明します。

  1. パッケージの利用
  • 例:WDI など。何度も、ダウンロードしなくて良いよいに、書き出しておき、2 を使うとよい。write(df_name, "./data/name.csv")
  1. コンピュータ上にある CSV などのテキストファイルを読み込む
  • 例:df_name <- read_csv("./data/file_name.csv")
  1. インターネット上のデータのアドレス(URL)を使って、CSV などのテキストファイルを読み込む。
  • 例:df_name <- read_csv(url_of_a_csv)
  1. コンピュータ上にある、Excel ファイルなどのデジタルファイルを読み込む。まず、library(readxl)
  • 例:df_name <- read_excel("./data/file_name.xlsx")
  1. サイトからダウンロードして、Project のデータフォルダに移す。または、データのアドレス(URL)がわかっていれば、直接ダウンロード。
  • 例:`download.file(url_of_a_data, destfile = “./data/data_name”)
  1. クリップボードにコピーして読み込む。
  • 例:df_name <- read_delim(clipboard())

2.1.3 WDIcache() の扱い

二つの、ファイルが一つになった、リストであるため、違って命令を使います。

wdi_cache <- WDIcache()
write_rds(wdi_cache, "./wdi_cache.RData")
wdi_cache <- read_rds("./wdi_cache.RData")

2.1.4 国際機関のデータ International Institutions’ Data

url_un_pop <- "https://data.un.org/_Docs/SYB/CSV/SYB65_1_202209_Population,%20Surface%20Area%20and%20Density.csv"
df_un_pop0 <- read_csv(url_un_pop)
New names:Rows: 7874 Columns: 7── Column specification ──────────────────────────────────────────────────────────
Delimiter: ","
chr (7): T02, Population, density and surface area, ...3, ...4, ...5, ...6, ...7
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
df_un_pop0
url_un_pop <- "https://data.un.org/_Docs/SYB/CSV/SYB65_1_202209_Population,%20Surface%20Area%20and%20Density.csv"
df_un_pop <- read_csv(url_un_pop, skip=1)
New names:Rows: 7873 Columns: 7── Column specification ──────────────────────────────────────────────────────────
Delimiter: ","
chr (4): ...2, Series, Footnotes, Source
dbl (2): Region/Country/Area, Year
num (1): Value
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
df_un_pop
df_un_pop %>% distinct(`Region/Country/Area`, `...2`)
df_un_pop %>% filter(`Region/Country/Area` %in% c(2,19,142,150,9), Series == "Population mid-year estimates (millions)") %>%
  ggplot(aes(Year, Value, fill = `...2`)) + geom_area(col="black") +
  labs(title = "Population mid-year estimates (millions) of the World")

2.2 OECD data

2.2.1 Definition of GDP per hour worked

GDP per hour worked is a measure of labour productivity. It measures how efficiently labour input is combined with other factors of production and used in the production process. Labour input is defined as total hours worked of all persons engaged in production. Labour productivity only partially reflects the productivity of labour in terms of the personal capacities of workers or the intensity of their effort. The ratio between the output measure and the labour input depends to a large degree on the presence and/or use of other inputs (e.g. capital, intermediate inputs, technical, organisational and efficiency change, economies of scale). This indicator is measured in USD (constant prices 2010 and PPPs) and indices.

労働時間当たりGDPは、労働生産性の指標である。これは、労働投入量が他の生産要素と組み合わされ、生産プロセスでどれだけ効率的に利用されたかを測定するものである。労働投入量は、生産に従事するすべての人の総労働時間として定義される。労働生産性は、労働者の個人的能力や努力の強さといった労働の生産性を部分的にしか反映していない。アウトプット指標と労働投入量の比率は、他の投入物(資本、中間投入物、技術・組織・効率の変化、規模の経済など)の存在や利用に大きく左右される。この指標は、米ドル(2010年の恒常価格およびPPP)および指標で測定されています。

df_oecd_productivity <- read_csv("./data/DP_LIVE_21022023111712065.csv")
Rows: 3894 Columns: 8── Column specification ──────────────────────────────────────────────────────────
Delimiter: ","
chr (6): LOCATION, INDICATOR, SUBJECT, MEASURE, FREQUENCY, Flag Codes
dbl (2): TIME, Value
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
df_oecd_productivity
df_oecd_productivity$LOCATION %>% unique()
 [1] "AUS"       "AUT"       "BEL"       "CAN"       "CZE"       "DNK"      
 [7] "FIN"       "FRA"       "DEU"       "GRC"       "HUN"       "ISL"      
[13] "IRL"       "ITA"       "JPN"       "KOR"       "LUX"       "MEX"      
[19] "NLD"       "NZL"       "NOR"       "POL"       "PRT"       "SVK"      
[25] "ESP"       "SWE"       "CHE"       "TUR"       "GBR"       "USA"      
[31] "CHL"       "EST"       "ISR"       "RUS"       "SVN"       "OECD"     
[37] "EU28"      "G-7"       "LVA"       "LTU"       "EA19"      "ZAF"      
[43] "CRI"       "BGR"       "HRV"       "ROU"       "EU27_2020" "COL"      
df_oecd_productivity$INDICATOR %>% unique()
[1] "GDPHRWKD"
df_oecd_productivity$SUBJECT %>% unique()
[1] "TOT"
df_oecd_productivity$MEASURE %>% unique()
[1] "USD"     "IDX2015"
df_oecd_productivity$FREQUENCY %>% unique()
[1] "A"
df_oecd_productivity$TIME %>% unique()
df_oecd_productivity %>% 
  filter(MEASURE == "USD", TIME == 2021) %>%
  select(LOCATION, Value) %>%
  arrange(desc(Value))
df_oecd_productivity %>% 
  filter(LOCATION %in% c("JPN", "OECD", "G-7", "EU28")) %>%
  filter(MEASURE == "USD") %>%
  ggplot(aes(TIME, Value, col = LOCATION)) + geom_line() + 
  labs(title="GDP per hour worked", subtitle="Total, 2015=100, 2021 or latest available")

2.2.2 Education

Adult education level: https://data.oecd.org/eduatt/adult-education-level.htm

df_oecd_education_level <- read_csv("./data/DP_LIVE_21022023120132654.csv")
Rows: 7330 Columns: 8── Column specification ──────────────────────────────────────────────────────────
Delimiter: ","
chr (5): LOCATION, INDICATOR, SUBJECT, MEASURE, FREQUENCY
dbl (2): TIME, Value
lgl (1): Flag Codes
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
df_oecd_education_level

2.3 World Inequality Report 2022

library(readxl)
url_summary <- "https://wir2022.wid.world/www-site/uploads/2022/03/WIR2022TablesFigures-Summary.xlsx"
download.file(url = url_summary, destfile = "./data/WIR2022s.xlsx", mode = "wb") 
trying URL 'https://wir2022.wid.world/www-site/uploads/2022/03/WIR2022TablesFigures-Summary.xlsx'
Content type 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' length 908659 bytes (887 KB)
==================================================
downloaded 887 KB
excel_sheets("./data/WIR2022s.xlsx")
 [1] "Index"     "F1"        "F2"        "F3"        "F4"        "F5."      
 [7] "F6"        "F7"        "F8"        "F9"        "F10"       "F11"      
[13] "F12"       "F13"       "F14"       "F15"       "T1"        "data-F1"  
[19] "data-F2"   "data-F3"   "data-F4"   "data-F5"   "data-F6"   "data-F7"  
[25] "data-F8"   "data-F9"   "data-F10"  "data-F11"  "data-F12"  "data-F13."
[31] "data-F14." "data-F15" 
df1_wir <- read_excel("./data/WIR2022s.xlsx", sheet = "data-F1")
New names:
df1_wir
df1_wir %>% select(cat = ...1, 2:4) %>%
  pivot_longer(2:4, names_to = "group", values_to = "value") %>%
  ggplot(aes(x = cat, y = value, fill = group)) +
  geom_col(position = "dodge") + 
  scale_y_continuous(labels = scales::percent_format(accuracy = 1)) + 
  geom_text(aes(x = cat, y = value, group = group, label = scales::label_percent(accuracy=1)(value)), vjust = -0.08,
            position = position_dodge(0.9)) + 
  labs(title = "Figure 1. Global income and wealth inequality, 2021",
       x = "", y = "Share of total income or wealth", fill = "")

df2_wir <- read_delim(clipboard())
Rows: 8 Columns: 5── Column specification ──────────────────────────────────────────────────────────
Delimiter: "\t"
chr (4): iso, Bottom 50%, Middle 40%, Top 10%
dbl (1): year
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
df2_wir
df2_wir2 <- read_excel("./data/WIR2022s.xlsx", sheet = "data-F2")
df2_wir2
df2_wir2 %>% pivot_longer(3:5, names_to = "level", values_to = "value") %>%
  ggplot(aes(x = iso, y = value, fill = level)) +
  geom_col(position = "dodge") + 
  scale_x_discrete(labels = function(x) stringr::str_wrap(x, width = 8)) +
  scale_y_continuous(labels = scales::percent_format(accuracy = 1)) +
  labs(title = "Figure 2. The poorest half lags behind Bottom 50%, middle 40% \nand top 10% income shares across the world in 2021",
       x = "", y = "Share of national income (%)", fill = "")

2.3.0.2 References

2.3.1 EDA by R Studio: Step 4 - Data Trasnformation

4.1. Look at the data: suppose df is the data frame

  • It is a good option to change into a tibble: dt <- as_tibble(df)
  • head(df), str(df), summary(df), dt, glimpse(dt)

4.2. Look at each variable

  • categorical? numerical?
  • factor? - forcats

4.3. Variation of each data: suppose x1 is a column name.

  • df %>% ggplot() + geom_histogram(aes(x1), bins = 30)

  • df %>% drop_na(x1): see the rows with a value in x1. If the value is NA, the row is not shown.

    • df_wo_na <- df %>% drop_na(x1) if you want to use only the rows without NA in x1

4.4. Use dpylr and tidyr to change column names, tidy data, and/or summarize data

  • rename, select, filter, arrange, mutate, pivot_longer(), pivot_wider(), group_by and summarize

2.3.1.1 References

2.3.2 EDA by R Studio: Step 5 - Visualize Data

5.1. In combination with Stap 4 - data transformation, try various data visualization.

  • What type of variation occurs within my variables?
  • What type of covariation occurs between my variables?

5.2. Keep a record of what you can observe by the visualization

5.3. Edit the list of questions by adding or polishing

5.4. Select several informative chart and add options

5.5. Look at examples from the textbooks or teaching site to have better visualization

2.3.2.1 References

2.3.3 EDA by R Studio: Step 6 - Conclusions and Questions for Further Study

  1. EDA is an iterative cycle that helps you understand what your data says. When you do EDA, you:

  2. Generate questions about your data

  3. Search for answers by visualising, transforming, and/or modeling your data

Use what you learn to refine your questions and/or generate new questions

EDA is an important part of any data analysis. You can use EDA to make discoveries about the world; or you can use EDA to ensure the quality of your data, asking questions about whether the data meets your standards or not.

2.4 Transforming Data: dplyr, tidyr

2.5 Visualizing Data: ggplot2

  • geom_smooth()

2.6 Templates

2.7 Practicum

3 DAY 3:2月24日

3.1 Importing Data

3.1.0.1 日本語データ

学校種類別進学率の推移: https://empowerment.tsuda.ac.jp/detail/82584

url_school_jp <- "https://www.gender.go.jp/about_danjo/whitepaper/r02/zentai/html/honpen/csv/zuhyo01-04-01.csv"
guess_encoding(url_school_jp, n_max = 10000, threshold = 0.2)
df_school_jp <- read_csv(url_school_jp, locale = locale(encoding = "Shift_JIS"), skip=2)
df_school_jp 
df_edu0 <- df_school_jp 
colnames(df_edu0) <- c("year", "highschool_m", "highschool_f", "vocational_m", "vocational_f", "university_m", "university_f", "juniorcollege_f", "gradschool_m", "gradschool_f")
df_edu00 <- df_edu0 %>% mutate(year = 1950:2019, 
                   highschool = (highschool_m + highschool_f)/2,
                   vocational = (vocational_m + vocational_f)/2,
                   university = (university_m + university_f)/2, 
                   juniorcollege = juniorcollege_f,
                   gradschool = (gradschool_m + gradschool_f)/2) 
df_edu00 %>% filter(year >= 1954) %>% select(-(2:10)) %>% 
  pivot_longer(3:5, names_to = "schools", values_to = "percentage") %>%
  mutate(types = factor(schools, levels = c("vocational", "juniorcollege", "university"))) %>%
  pivot_longer(c(highschool, gradschool), names_to = "highgrad", values_to ="value") %>%
  mutate(high_grad = factor(highgrad, levels = c("highschool", "gradschool"))) %>%
  ggplot() +
  geom_area(aes(x = year, y = percentage, fill = types)) +
  geom_line(aes(x = year, y = value, linetype = high_grad)) + 
  scale_x_continuous(breaks = round(seq(1960, 2020, by =10),1)) + 
  scale_y_continuous(breaks = round(seq(0, 100, by =10),1)) + 
  labs(title = "Tertially Education After Highschool", 
       subtitle = "with Highschool Graduates and Graduate School", fill = "", linetype = "")

3.2 Exploratory Data Analysis; Workflow

3.3 Transforming Data

  • filter(), select(), arrange(), mutate(), group_by(), summarize()

3.4 Visualizing Data

There is no rule about which questions you should ask to guide your research. However, two types of questions will always be useful for making discoveries within your data. You can loosely word these questions as:

  • What type of variation occurs within my variables?
    • Variance - distribution
  • What type of covariation occurs between my variables?
    • Covariance - correlation

3.5 Combining Data

3.6 Practicum

3.7 Questions and Answers

4 参考

4.1 RNotebook の活用

下のリンクを開き、右上の Code ボタンから、Download Rmd を選択すると、ダウンロードできますから、ダインロードしたものを、プロジェクト・フォールダーに移動またはコピーしてください。ダウンロードできないときは、Ctrl を押しながら、Download Rmd をクリックすると、Save As で保存できると思います。ブラウザーによって仕様が異なりますから、適切な方法を選んでください。

Windows でも、Mac でも提供されている、Google Chrome の場合には、Code ボタンから、ダンロードされるはずです。

4.2 クラウド - Posit Cloud

RStudio Cloudは、誰でもオンラインでデータサイエンスを行い、共有し、教え、学ぶことができる、軽量でクラウドベースのソリューションです。

4.2.1 クラウドサービス How to Start Posit Cloud

  1. Go to https://posit.cloud/
  2. Sign Up: top right
  3. Email address or Google account
  4. New Project: Project Name

4.3 練習問題 Posit Primers

Posit Primers https://posit.cloud/learn/primers

4.3.1 最初の演習 The Basics – r4ds: Explore, I

5 R Markdown

5.1 最初の一歩 Let’s get started!

  1. 準備:パッケージのインストール
  2. R Notebook
  3. 日本語のテンプレート
  4. R Markdown いくつかの Output
  5. R Script 実行記録
  6. パッケージ - Packages

5.2 2. R Notebook

R Markdownはデータサイエンスのためのオーサリングフレームワーク。

コード(プログラム)とその実行結果、を記録・表示し、高品質のレポートの作成を可能にします。

R Notebook は、独立してインタラクティブに実行できるチャンクを持つR Markdownドキュメントの一つの形式で、入力のすぐ下に出力が表示することができます。

  1. File > New File > R Notebook
  2. Save with a file name, say, test-notebook
  3. Preview by [Preview] button
  4. Run Code Chunk plot(cars) and then Preview again.

5.3 3. 日本語のテンプレート

下のリンクを開き、右上の Code ボタンから、Download Rmd を選択すると、ダウンロードできますから、ダインロードしたものを、プロジェクト・フォールダーに移動またはコピーしてください。ダウンロードできないときは、Ctrl を押しながら、Download Rmd をクリックすると、Save As で保存できると思います。ブラウザーによって仕様が異なりますから、適切な方法を選んでください。

Windows でも、Mac でも提供されている、Google Chrome の場合には、Code ボタンから、ダンロードされるはずです。

LS0tCnRpdGxlOiAiRUNPMjMyIFLjgpLkvb/jgaPjgZ/ntYzmuIjjg4fjg7zjgr/jga7lj47pm4bjgajliIbmnpDjga7mlrnms5UiCmF1dGhvcjogIumItOacqOWvm++8iEhpcm9zaGkgU3V6dWtp77yJIgpkYXRlOiAiYHIgU3lzLkRhdGUoKWAiCm91dHB1dDoKICBodG1sX25vdGVib29rOgogICAgdG9jOiB5ZXMKICAgIHRvY19mbG9hdDogeWVzCiAgICBoaWdobGlnaHQ6IHRhbmdvCiAgICB0aGVtZTogY2VydWxlYW4KICAgIG51bWJlcl9zZWN0aW9uczogeWVzCiAgaW9zbGlkZXNfcHJlc2VudGF0aW9uOgogICAgaGlnaGxpZ2h0OiB0YW5nbwogICAgd2lkZXNjcmVlbjogeWVzCiAgaHRtbF9kb2N1bWVudDoKICAgIHRvYzogeWVzCiAgICBkZl9wcmludDogcGFnZWQKLS0tCgpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRSwgZXZhbD1GQUxTRX0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGVjaG8gPSBGQUxTRSkKYGBgCgojIERBWSAx77yaMuaciDIw5pelCgojIyBSU3R1ZGlvIOOBpyBQcm9qZWN0IOOBruS9nOaIkAoKIyMjIOeiuuiqjQoKMS4gIFIg44GoIFIgU3R1ZGlvIOOBruOCpOODs+OCueODiOODvOODqwoyLiAgUlN0dWRpbzogTmV3IFByb2plY3Qg5L2c5oiQCgotICAgUiBTdHVkaW8g44Gu6LW35YuVCi0gICBOZXcgUHJvamVjdDogZWNvMjMyLCBlY28yMzIuUnByb2oKCjMuICBTYXZlIOOBl+OBpuOAgee1guS6hgo0LiAg44OX44Ot44K444Kn44Kv44OI44KS6LW35YuV56K66KqNCgojIyDln7rmnKzjgrPjg57jg7Pjg4kgLSBpbiBDb25zb2xlCgotICAgYGhlYWQoY2FycylgCi0gICBgc3RyKGNhcnMpYAotICAgYHN1bW1hcnkoY2FycylgCi0gICBgZGZfY2FycyA8LSBjYXJzYAogICAgLSAgIGA8LWAg44GoIGBfYCDjgaggYCU+JWAg44GoIFxgIGJhY2sgdGljayDjga7norroqo0KLSAgIGBWaWV3KGNhcnMpYCDjgb7jgZ/jga/jgIHlj7PkuIrjga4gRW52aXJvbm1lbnQg44GL44KJ44CBYGRmX2NhcnNgIOOCkuOCr+ODquODg+OCrwotICAgYD9jYXJzYCDjgb7jgZ/jga8gSGVscCDmpJzntKLnqpPjgacgYGNhcnNgLCBgaGVhZGAg44Gq44GpCgrjgYrjgZnjgZnjgoHvvJpgU3lzLnNldGVudihMQU5HID0gImVuIilgCgojIyBQYWNrYWdlIOOBrueiuuiqjeOBqOOCpOODs+OCueODiOODvOODqwoKUiBwYWNrYWdlcyBhcmUgZXh0ZW5zaW9ucyB0byB0aGUgUiBzdGF0aXN0aWNhbCBwcm9ncmFtbWluZyBsYW5ndWFnZSBjb250YWluaW5nIGNvZGUsIGRhdGEsIGFuZCBkb2N1bWVudGF0aW9uIGluIGEgc3RhbmRhcmRpc2VkIGNvbGxlY3Rpb24gZm9ybWF0IHRoYXQgY2FuIGJlIGluc3RhbGxlZCBieSB1c2VycyBvZiBSIHVzaW5nIFRvb2wgXD4gSW5zdGFsbCBQYWNrYWdlcyBpbiB0aGUgdG9wIG1lbnUgYmFyIG9mIFIgU3R1ZGlvLgoKUuODkeODg+OCseODvOOCuOOBr+OAgVLjga7mi6HlvLXmqZ/og73jgafjgIHjgrPjg7zjg4njgIHjg4fjg7zjgr/jgIHjg4njgq3jg6Xjg6Hjg7Pjg4jjgpLmqJnmupbljJbjgZXjgozjgZ/jgrPjg6zjgq/jgrfjg6fjg7PlvaLlvI/jgaflkKvjgpPjgafjgYrjgorjgIHmqJnmupbnmoTjgarjgoLjga7jga/jgIFSIFN0dWRpbyDjga4gVG9wIEJhciDjga4gVG9vbCBcPiBJbnN0YWxsIFBhY2thZ2VzIOOBi+OCieOCpOODs+OCueODiOODvOODq+OBp+OBjeOBvuOBmeOAggoKLSAgIE1pbmltdW06IGB0aWR5dmVyc2VgLCBgcm1hcmtkb3duYCwgYFdESWAKCuOBguOBqOOBi+OCieS9v+OBhuOBruOBp+OAgeODreODvOODieOBl+OBpuOBiuOBjeOBvuOBmeOAguacgOWIneOBq+asoeOBruOCiOOBhuOBquOCs+ODvOODieOCkuWun+ihjOOBl+OBvuOBmeOAguWPs+OBruS4ieinkuOCkuaKvOOBl+OBvuOBmeOAggoKYGBge3J9CmxpYnJhcnkodGlkeXZlcnNlKQpsaWJyYXJ5KFdESSkKYGBgCgojIyBSIE1hcmtkb3duIOWFpemWgAoKIyMjIFIgTm90ZWJvb2sKClIgTWFya2Rvd27jga/jg4fjg7zjgr/jgrXjgqTjgqjjg7Pjgrnjga7jgZ/jgoHjga7jgqrjg7zjgrXjg6rjg7PjgrDjg5Xjg6zjg7zjg6Djg6/jg7zjgq/jgIIKCuOCs+ODvOODie+8iOODl+ODreOCsOODqeODoO+8ieOBqOOBneOBruWun+ihjOe1kOaenOOAgeOCkuiomOmMsuODu+ihqOekuuOBl+OAgemrmOWTgeizquOBruODrOODneODvOODiOOBruS9nOaIkOOCkuWPr+iDveOBq+OBl+OBvuOBmeOAggoKUiBOb3RlYm9vayDjga/jgIHni6znq4vjgZfjgabjgqTjg7Pjgr/jg6njgq/jg4bjgqPjg5bjgavlrp/ooYzjgafjgY3jgovjg4Hjg6Pjg7Pjgq/jgpLmjIHjgaRSIE1hcmtkb3du44OJ44Kt44Ol44Oh44Oz44OI44Gu5LiA44Gk44Gu5b2i5byP44Gn44CB5YWl5Yqb44Gu44GZ44GQ5LiL44Gr5Ye65Yqb44GM6KGo56S644GZ44KL44GT44Go44GM44Gn44GN44G+44GZ44CCCgoxLiAgRmlsZSBcPiBOZXcgRmlsZSBcPiBSIE5vdGVib29rCjIuICBTYXZlIHdpdGggYSBmaWxlIG5hbWUsIHNheSwgdGVzdC1ub3RlYm9vawozLiAgUHJldmlldyBieSBbUHJldmlld10gYnV0dG9uCjQuICBSdW4gQ29kZSBDaHVuayBwbG90KGNhcnMpIGFuZCB0aGVuIFByZXZpZXcgYWdhaW4uCgojIyBXb3JsZCBEZXZlbG9wbWVudCBJbmRpY2F0b3IgKFdESSkKCmBgYHtyIGNhY2hlPVRSVUV9CldESShjb3VudHJ5ID0gImFsbCIsIGluZGljYXRvciA9IGMoZ2RwID0gIk5ZLkdEUC5NS1RQLkNEIiksCiAgICBleHRyYT1UUlVFKSAlPiUgZHJvcF9uYShnZHApICU+JQogIGZpbHRlcih5ZWFyPT1tYXgoeWVhciksIGluY29tZSAhPSJBZ2dyZWdhdGVzIikgJT4lIAogIGRyb3BfbmEocmVnaW9uKSAlPiUgYXJyYW5nZShkZXNjKGdkcCkpCmBgYAoKYGBge3IgY2FjaGU9VFJVRX0KY2hvc2VuX2NvdW50cmllcyA8LSBjKCJVbml0ZWQgU3RhdGVzIiwiQ2hpbmEiLCAiSmFwYW4iLCAiR2VybWFueSIsICJVbml0ZWQgS2luZ2RvbSIsIkluZGlhIikKV0RJKGNvdW50cnkgPSBjKCJDTiIsIkdCIiwiSlAiLCJJTiIsIlVTIiwiREUiKSwgaW5kaWNhdG9yID0gYyhnZHAgPSAiTlkuR0RQLk1LVFAuQ0QiKSwgZXh0cmE9VFJVRSkgJT4lIGRyb3BfbmEoZ2RwKSAlPiUgCiAgZ2dwbG90KGFlcyh5ZWFyLCBnZHAsIGNvbCA9IGNvdW50cnkpKSArIGdlb21fbGluZSgpICsKICBsYWJzKHRpdGxlID0gIldESSBOWS5HRFAuTUtUUC5DRDogZ2RwIikKYGBgCgpgYGB7ciBjYWNoZT1UUlVFfQpXREkoY291bnRyeSA9IGMoIkNOIiwiSU4iLCJKUCIsIlVTIiksIAogICAgaW5kaWNhdG9yID0gYyhnZHBfZ3Jvd3RoX3JhdGUgPSAiTlkuR0RQLk1LVFAuS0QuWkciKSwgZXh0cmE9VFJVRSkgJT4lCiAgZHJvcF9uYShnZHBfZ3Jvd3RoX3JhdGUpICU+JSAKICBnZ3Bsb3QoYWVzKHllYXIsIGdkcF9ncm93dGhfcmF0ZSwgY29sID0gY291bnRyeSkpICsgZ2VvbV9saW5lKCkgKwogIGxhYnModGl0bGUgPSBwYXN0ZSgiV0RJIE5ZLkdEUC5NS1RQLktELlpHOiBnZHAgZ3Jvd3RoIHJhdGUiKSkKYGBgCgojIyMg5oyH5qiZIEluZGljYXRvcnMgKFdESSkKCi0gICBOWS5HRFAuTUtUUC5DRDogR0RQIChjdXJyZW50IFVTXCQpCi0gICBOWS5HRFAuTUtUUC5LRC5aRzogR0RQIGdyb3d0aCAoYW5udWFsICUpCgojIyMg5oyH5qiZIFdESSDjgpLmjqLjgZfjgabjgb/jgojjgYYKCj4gVGhlIFdvcmxkIERldmVsb3BtZW50IEluZGljYXRvcnMgaXMgYSBjb21waWxhdGlvbiBvZiByZWxldmFudCwgaGlnaC1xdWFsaXR5LCBhbmQgaW50ZXJuYXRpb25hbGx5IGNvbXBhcmFibGUgc3RhdGlzdGljcyBhYm91dCBnbG9iYWwgZGV2ZWxvcG1lbnQgYW5kIHRoZSBmaWdodCBhZ2FpbnN0IHBvdmVydHkuIFRoZSBkYXRhYmFzZSBjb250YWlucyAxLDQwMCB0aW1lIHNlcmllcyBpbmRpY2F0b3JzIGZvciAyMTcgZWNvbm9taWVzIGFuZCBtb3JlIHRoYW4gNDAgY291bnRyeSBncm91cHMsIHdpdGggZGF0YSBmb3IgbWFueSBpbmRpY2F0b3JzIGdvaW5nIGJhY2sgbW9yZSB0aGFuIDUwIHllYXJzLgoKPiBXREnjga/jgIHkuJbnlYzjga7plovnmbrnirbms4HjgajjgIHosqflm7Djgajjga7miKbjgYTjgavplqLjgZnjgovjgIHpganliIfjgafkuIros6rjgIHjgYvjgaTjgIHlm73pmpvnmoTjgavmr5TovIPlj6/og73jgarmmYLns7vliJfjga7ntbHoqIjjg4fjg7zjgr/jgpLnt6jnuoLjgZfjgZ/jgoLjga7jgafjgZnjgILjgZPjga7jg4fjg7zjgr/jg5njg7zjgrnjga/jgIEyMTfjga7ntYzmuIjjgag0MOS7peS4iuOBruWbveOCsOODq+ODvOODl+OBq+OBpOOBhOOBpjEsNDAw44Gu5pmC57O75YiX5oyH5qiZ44KS5ZCr44G/44CB5oyH5qiZ44Gu44OH44O844K/44Gu5aSa44GP44GvNTDlubTku6XkuIrliY3jgavpgaHjgovjgZPjgajjgYzjgafjgY3jgb7jgZnjgIIKCi0gICDkuJbnlYzpioDooYzvvIhXb3JsZCBCYW5r77yJOiA8aHR0cHM6Ly93d3cud29ybGRiYW5rLm9yZz4KLSAgIFdvcmxkIEJhbmsgT3BlbiBEYXRhOiA8aHR0cHM6Ly9kYXRhLndvcmxkYmFuay5vcmc+CiAgICAtICAgQ291bnRyeSAvIFtJbmRpY2F0b3JdKGh0dHBzOi8vZGF0YS53b3JsZGJhbmsub3JnL2luZGljYXRvcikgXD4gRmVhdHVyZWQgJiBBbGwgXD4gRGV0YWlscwotICAgW1dvcmxkIERldmVsb3BtZW50IEluZGljYXRvcnMgKFdESSldKGh0dHBzOi8vZGF0YXRvcGljcy53b3JsZGJhbmsub3JnL3dvcmxkLWRldmVsb3BtZW50LWluZGljYXRvcnMvKSA6CiAgICAtICAgVGhlbWVzOiBQb3ZlcnR5IGFuZCBJbmVxdWFsaXR5LCBQZW9wbGUsIEVudmlyb25tZW50LCBFY29ub215LCBTdGF0ZXMgYW5kIE1hcmtldHMsIEdsb2JhbCBMaW5rcwogICAgLSAgIE9wZW4gRGF0YSAmIERhdGFCYW5rOiBFeHBsb3JlIGRhdGEsIFF1ZXJ5IGRhdGFiYXNlCgojIyMg5oyH5qiZIFdESeOBruS+iwoKKiBOWS5HRFAuTUtUUC5DRDogR0RQIChjdXJyZW50IFVTJCkKKiBOWS5HRFAuREVGTC5LRC5aRzogSW5mbGF0aW9uLCBHRFAgZGVmbGF0b3IgKGFubnVhbCAlKQoqIFNMLlVFTS5UT1RMLk5FLlpTOiBVbmVtcGxveW1lbnQsIHRvdGFsICglIG9mIHRvdGFsIGxhYm9yIGZvcmNlKSAobmF0aW9uYWwgZXN0aW1hdGUpCiogQ1BUT1ROU1hOOiBDUEkgUHJpY2UsIG5vbWluYWwKKiBTTC5UTEYuQ0FDVC5NQS5ORS5aUzogTGFib3IgZm9yY2UgcGFydGljaXBhdGlvbiByYXRlLCBtYWxlICglIG9mIG1hbGUgcG9wdWxhdGlvbiBhZ2VzIDE1KykgKG5hdGlvbmFsIGVzdGltYXRlKQoqIFNMLlRMRi5DQUNULkZFLk5FLlpTOiBMYWJvciBmb3JjZSBwYXJ0aWNpcGF0aW9uIHJhdGUsIGZlbWFsZSAoJSBvZiBtYWxlIHBvcHVsYXRpb24gYWdlcyAxNSspIChuYXRpb25hbCBlc3RpbWF0ZSkKCiMjIyDnt7Tnv5IgMS4gLSDoqr/jgbnjgabjgb/jgZ/jgYQgV0RJCgrjgYTjgY/jgaTjgYvjgIHjg6rjgrnjg4jjgZfjgabjgb/jgb7jgZfjgofjgYbjgIIKCiMjIFdESSDjg5Hjg4PjgrHjg7zjgrgKCmBXRElgIOODkeODg+OCseODvOOCuOOBp+OAgeODh+ODvOOCv+OCkuODgOOCpuODs+ODreODvOODieOBl+OBn+OCiuOAgeaOouOBl+OBn+OCiuOAgeips+e0sOaDheWgseOCkuW+l+OBn+OCiuOBp+OBjeOBvuOBmeOAggoKIyMjIOaMh+aomSBXREkg5qSc57SiCgojIyMjIOaknOe0ouS+iyAx77yIV0RJ5ZCN77yJCgpgYGB7ciBjYWNoZT1UUlVFfQpXRElzZWFyY2goc3RyaW5nID0gImdkcCIsIGZpZWxkID0gIm5hbWUiLCBzaG9ydCA9IFRSVUUsIGNhY2hlID0gTlVMTCkKYGBgCgogIAojIyMjIOaknOe0ouS+iyAy77yIV0RJ77yJCgpgYGB7ciBjYWNoZT1UUlVFfQpXRElzZWFyY2goc3RyaW5nID0gIk5ZLkdEUC5NS1RQLkNEIiwgZmllbGQgPSAiaW5kaWNhdG9yIiwgc2hvcnQgPSBUUlVFLCBjYWNoZSA9IE5VTEwpCmBgYAoKICAKIyMjIyDnt7Tnv5IgMi4gLSDmpJzntKLvvIhzaG9ydO+8iQoK5ZCN5YmN44Gn5qSc57Si77yIIiIg44Gu6ZaT44Gr44CB77yI44Gq44KL44G544GP57Ch5Y2Y44Gq77yJ5qSc57Si5paH5a2X5YiX44KS5YWl44KM44Gm44GP44Gg44GV44GE44CC77yJCgpgYGB7ciBldmFsPUZBTFNFLCBjYWNoZT1UUlVFfQpXRElzZWFyY2goc3RyaW5nID0gIiIsIGZpZWxkID0gIm5hbWUiLCBzaG9ydCA9IFRSVUUsIGNhY2hlID0gTlVMTCkKYGBgCgpJbmRpY2F0b3Ig44Gn5qSc57Si77yIIiIg44Gu6ZaT44Gr44CB6Kq/44G544Gf44GEIGluZGljYXRvciDjgpLlhaXjgozjgabjgY/jgaDjgZXjgYTjgILvvIkKCmBgYHtyIGV2YWw9RkFMU0UsIGNhY2hlPVRSVUV9CldESXNlYXJjaChzdHJpbmcgPSAiIiwgZmllbGQgPSAiaW5kaWNhdG9yIiwgc2hvcnQgPSBUUlVFLCBjYWNoZSA9IE5VTEwpCmBgYAoKICAKIyMjIyDoqbPjgZfjgYTmg4XloLHjgpLlvpfjgovjgavjga8KCmBzaG9ydCA9IEZBTFNFYCDjgajjgZfjgb7jgZnjgILmmYLplpPjgYzjgYvjgYvjgovjga7jgafjgIHmpJzntKLjga/jgIFJbmRpY2F0b3Ig44Go44CB5ZCN5YmN44Gq44Gp44Gu5oOF5aCx44KS44KC44Gj44Gf44OV44Kh44Kk44Or44KS5omL5YWD44Gr5oyB44Gj44Gm44GK44GP44GT44Go44Gr44GX44G+44GZ44CCCgpgYGB7ciBjYWNoZT1UUlVFfQp3ZGlfY2FjaGUgPC0gV0RJY2FjaGUoKQpgYGAKCuWPs+S4iuOBrueqk+aeoO+8iHBhbmXvvInjgYvjgonjgIFgd2RpX2NhY2hlYCDjgpLmjqLjgZfjgabjgIHkuK3ouqvjgpLopovjgabjgb/jgb7jgZfjgofjgYbjgIJzZXJpZXMg44Go44CBY291bnRyeSDjga7kuozjgaTjga7jg4fjg7zjgr/jg7vjg5Xjg6zjg7zjg6DjgYvjgonjgarjgaPjgabjgYTjgovjg6rjgrnjg4jjgafjgZnjgILkuInop5LljbDjgoTjgIHlj7PjgYvjgonkuoznlarnm67jga7lt7vnianjga7jgojjgYbjgarjgqLjgqTjgrPjg7PjgpLjgq/jg6rjg4Pjgq/jgZnjgovjgajkuK3ouqvjgYzopovjgYjjgb7jgZnjgIIKCiAgCiMjIyMg5qSc57Si5L6LIDPvvIhXREnlkI3vvIkKCmBgYHtyfQpXRElzZWFyY2goc3RyaW5nID0gIkNQSSBQcmljZSIsIGZpZWxkID0gIm5hbWUiLCBzaG9ydCA9IEZBTFNFLCBjYWNoZSA9IHdkaV9jYWNoZSkKYGBgCgotIENQVE9UTlNYTjogQ1BJIFByaWNlLCBub21pbmFsCiAgLSBUaGUgY29uc3VtZXIgcHJpY2UgaW5kZXggcmVmbGVjdHMgdGhlIGNoYW5nZSBpbiBwcmljZXMgZm9yIHRoZSBhdmVyYWdlIGNvbnN1bWVyIG9mIGEgY29uc3RhbnQgYmFza2V0IG9mIGNvbnN1bWVyIGdvb2RzLiBEYXRhIGlzIG5vdCBzZWFzb25hbGx5IGFkanVzdGVkLgoKIyMjIyDmpJzntKLkvosgNO+8iFdESe+8iQoKYGBge3J9CldESXNlYXJjaChzdHJpbmcgPSAiTlkuR0RQLk1LVFAuS0QuWkciLCBmaWVsZCA9ICJpbmRpY2F0b3IiLCBzaG9ydCA9IEZBTFNFLCBjYWNoZSA9IHdkaV9jYWNoZSkKYGBgCgogIAojIyMjIOe3tOe/kiAyIC0g5qSc57Si77yIbG9uZyB3LyBjYWNoZe+8iQoKYHN0cmluZ2Ag44Go44CBYGZpZWxkYCDjgpLjgIHjgbXjgZ/jgaTjgajjgoLlhaXjgozjgabjgY/jgaDjgZXjgYTjgIIKCmBgYHtyIGV2YWw9RkFMU0V9CldESXNlYXJjaChzdHJpbmcgPSAiIiwgZmllbGQgPSAiIiwgc2hvcnQgPSBGQUxTRSwgY2FjaGUgPSB3ZGlfY2FjaGUpCmBgYAoKCgojIyMg5oyH5qiZIFdESSDjg4fjg7zjgr/jga7jg4Djgqbjg7Pjg63jg7zjg4kKCkluZGljYXRvciDjgYzmsbrjgb7jgaPjgZ/jgonjgIHjg4Djgqbjg7Pjg63jg7zjg4njgZfjgb7jgZnjgIIKCmBgYHtyIGV2YWw9RkFMU0V9Cj9XREkKYGBgCgogIAojIyMjIOODgOOCpuODs+ODreODvOODieS+iyAxLTEKCmBgYHtyIGNhY2hlPVRSVUV9CmRmX2dkcDEgPC0gV0RJKGNvdW50cnkgPSAiYWxsIiwgaW5kaWNhdG9yID0gIk5ZLkdEUC5NS1RQLkNEIikKZGZfZ2RwMQpgYGAKCiAgCiMjIyMg44OA44Km44Oz44Ot44O844OJ5L6LIDEtMgoKYGBge3IgY2FjaGU9VFJVRX0KZGZfZ2RwMiA8LSBXREkoY291bnRyeSA9ICJhbGwiLCBpbmRpY2F0b3IgPSBjKGdkcCA9ICJOWS5HRFAuTUtUUC5DRCIpKQpkZl9nZHAyCmBgYAoKICAKIyMjIyDjg4Djgqbjg7Pjg63jg7zjg4nkvosgMS0zCgpgYGB7ciBjYWNoZT1UUlVFfQpkZl9nZHAzIDwtIFdESShjb3VudHJ5ID0gImFsbCIsIGluZGljYXRvciA9IGMoZ2RwID0gIk5ZLkdEUC5NS1RQLkNEIiksIGV4dHJhPVRSVUUsIGNhY2hlPXdkaV9jYWNoZSkKZGZfZ2RwMwpgYGAKCiAgCiMjIyMg44OA44Km44Oz44Ot44O844OJ5L6LIDEtNAoKYGBge3IgY2FjaGU9VFJVRX0KZGZfZ2RwNCA8LSBXREkoY291bnRyeSA9IGMoIkNOIiwiR0IiLCJKUCIsIklOIiwiVVMiLCJERSIpLCBpbmRpY2F0b3IgPSBjKGdkcCA9ICJOWS5HRFAuTUtUUC5DRCIpLCBleHRyYT1UUlVFLCBjYWNoZT13ZGlfY2FjaGUpCmRmX2dkcDQKYGBgCgojIyMjIOODgOOCpuODs+ODreODvOODieS+iyAyLTEKCiogTlkuR0RQLkRFRkwuS0QuWkc6IEluZmxhdGlvbiwgR0RQIGRlZmxhdG9yIChhbm51YWwgJSkKKiBDUFRPVE5TWE46IENQSSBQcmljZSwgbm9taW5hbAoKYGBge3IgY2FjaGU9VFJVRX0KZGZfZ2RwMjEgPC0gV0RJKGNvdW50cnkgPSAiYWxsIiwgCiAgICAgICAgICAgICAgICBpbmRpY2F0b3IgPSBjKGdkcF9kZWZsYXRvciA9ICJOWS5HRFAuREVGTC5LRC5aRyIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjcGlfcHJpY2UgPSAiQ1BUT1ROU1hOIiksIAogICAgICAgICAgICAgICAgZXh0cmE9VFJVRSwgY2FjaGU9d2RpX2NhY2hlKQpkZl9nZHAyMQpgYGAKCmBgYHtyfQpzdHIoZGZfZ2RwMjEpCmBgYAoKYGBge3J9CnN1bW1hcnkoZGZfZ2RwMjEpCmBgYAoK5Y+z5LiK44Gu56qT5p6g44Gu44CBRW52aXJvbm1lbnQg44KC6KaL44Gm44G/44G+44GX44KH44GG44CCCgojIyDlj6/oppbljJYgVmlzdWFsaXphdGlvbgoK44Kw44Op44OV77yIQ2hhcnTvvInjgpLmj4/jgYTjgaboppbopprljJbjgZfjgojjgYYKCiMjIyDjgrDjg6njg5UgMQoKYGBge3J9CmRmX2dkcDQgJT4lIGdncGxvdChhZXMoeWVhciwgZ2RwLCBjb2w9Y291bnRyeSkpICsgZ2VvbV9saW5lKCkKYGBgCgojIyMg44Kw44Op44OVIDIKCmBgYHtyfQpkZl9nZHA0ICU+JSBkcm9wX25hKGdkcCkgJT4lIAogIGdncGxvdChhZXMoeWVhciwgZ2RwLCBjb2w9Y291bnRyeSkpICsgZ2VvbV9saW5lKCkgKwogIGxhYnModGl0bGUgPSBwYXN0ZSgiV0RJIC0gTlkuR0RQLk1LVFAuQ0Q6ICIsICJnZHAiKSkKYGBgCgojIyMg44OG44Oz44OX44Os44O844OIIFRlbXBsYXRlcwoKIyMjIyDkuIDjgaTjga7lm73jgavjgaTjgYTjgabjga7jgIHkuIDjgaTjga7mjIfmqJnvvIhXREnvvInjgajjgIHjgZ3jga7nlaXnp7DjgYvjgonjgIHmipjnt5rjgrDjg6njg5XjgpLkvZzmiJAKCkxpbmUgUGxvdCB3aXRoIG9uZSBpbmRpY2F0b3Igd2l0aCBhYmJyZXZpYXRpb24gYW5kIG9uZSBjb3VudHJ5CgpgYGB7ciBjYWNoZT1UUlVFfQpjaG9zZW5faW5kaWNhdG9yIDwtICJTTC5VRU0uVE9UTC5ORS5aUyIKc2hvcnRfbmFtZSA8LSAidW5lbXBsb3ltZW50IgpjaG9zZW5fY291bnRyeSA8LSAiVW5pdGVkIFN0YXRlcyIKV0RJKGNvdW50cnkgPSAiYWxsIiwgaW5kaWNhdG9yID0gYyhzaG9ydF9uYW1lID0gY2hvc2VuX2luZGljYXRvciksIGV4dHJhPVRSVUUsIGNhY2hlPXdkaV9jYWNoZSkgJT4lCiAgZmlsdGVyKGNvdW50cnkgPT0gY2hvc2VuX2NvdW50cnkpICU+JSAKICBnZ3Bsb3QoYWVzKHllYXIsIHNob3J0X25hbWUpKSArIGdlb21fbGluZSgpICsKICBsYWJzKHRpdGxlID0gcGFzdGUoIldESSAiLCBjaG9zZW5faW5kaWNhdG9yLCAiOiAiLCBzaG9ydF9uYW1lLCAiIC0gIiwgY2hvc2VuX2NvdW50cnkpLAogICAgICAgeSA9IHNob3J0X25hbWUpCmBgYAoKIyMjIyDkuIDjgaTjga7lm73jgavjgaTjgYTjgabjga7jgIHkuIDjgaTjga7mjIfmqJnvvIhXREnvvInjgYvjgonjgIHmipjnt5rjgrDjg6njg5XjgpLkvZzmiJAKCkxpbmUgUGxvdCB3aXRoIG9uZSBpbmRpY2F0b3IgYW5kIG9uZSBjb3VudHJ5CgpgYGB7ciBjYWNoZT1UUlVFfQpjaG9zZW5faW5kaWNhdG9yIDwtICJTTC5VRU0uVE9UTC5ORS5aUyIKY2hvc2VuX2NvdW50cnkgPC0gIlVuaXRlZCBTdGF0ZXMiCldESShjb3VudHJ5ID0gImFsbCIsIGluZGljYXRvciA9IGMoY2hvc2VuX2luZGljYXRvciA9IGNob3Nlbl9pbmRpY2F0b3IpLCAKICAgIGV4dHJhPVRSVUUsIGNhY2hlPXdkaV9jYWNoZSkgJT4lCiAgZmlsdGVyKGNvdW50cnkgPT0gY2hvc2VuX2NvdW50cnkpICU+JSAKICBnZ3Bsb3QoYWVzKHllYXIsIGNob3Nlbl9pbmRpY2F0b3IpKSArIGdlb21fbGluZSgpICsKICBsYWJzKHRpdGxlID0gcGFzdGUoIldESSAiLCBjaG9zZW5faW5kaWNhdG9yLCAiIC0gIiwgY2hvc2VuX2NvdW50cnkpLCAKICAgICAgIHkgPSBjaG9zZW5faW5kaWNhdG9yKQpgYGAKCiMjIyMg44GE44GP44Gk44GL44Gu5Zu944Gr44Gk44GE44Gm44Gu44CB5LiA44Gk44Gu5oyH5qiZ77yIV0RJ77yJ44Go44CB44Gd44Gu55Wl56ew44GL44KJ44CB5oqY57ea44Kw44Op44OV44KS5L2c5oiQCgpMaW5lIFBsb3Qgd2l0aCBvbmUgaW5kaWNhdG9yIHdpdGggYWJicmV2aWF0aW9uIGFuZCBzZXZlcmFsIGNvdW50cmllcwoKYGBge3IgY2FjaGU9VFJVRX0KY2hvc2VuX2luZGljYXRvciA8LSAiU0wuVUVNLlRPVEwuTkUuWlMiCnNob3J0X25hbWUgPC0gInVuZW1wbG95bWVudCIKY2hvc2VuX2NvdW50cmllcyA8LSBjKCJVbml0ZWQgU3RhdGVzIiwiVW5pdGVkIEtpbmdkb20iLCAiSmFwYW4iKQpXREkoY291bnRyeSA9ICJhbGwiLCBpbmRpY2F0b3IgPSBjKHNob3J0X25hbWUgPSBjaG9zZW5faW5kaWNhdG9yKSwgZXh0cmE9VFJVRSwgY2FjaGU9d2RpX2NhY2hlKSAlPiUgZHJvcF9uYShzaG9ydF9uYW1lKSAlPiUgCiAgZmlsdGVyKGNvdW50cnkgJWluJSBjaG9zZW5fY291bnRyaWVzKSAlPiUgCiAgZ2dwbG90KGFlcyh5ZWFyLCBzaG9ydF9uYW1lLCBjb2wgPSBjb3VudHJ5KSkgKyBnZW9tX2xpbmUoKSArCiAgbGFicyh0aXRsZSA9IHBhc3RlKCJXREkgIiwgY2hvc2VuX2luZGljYXRvciwgIjogIiwgc2hvcnRfbmFtZSksIHkgPSBzaG9ydF9uYW1lKQpgYGAKCgojIyMjIOS4gOOBpOOBruWbveOBq+OBpOOBhOOBpuOBruOAgeS6jOOBpOOBruaMh+aome+8iFdESe+8ieOBqOOAgeOBneOBrueVpeensOOBi+OCieOAgeaKmOe3muOCsOODqeODleOCkuS9nOaIkAoKTGluZSBQbG90IHdpdGggdHdvIGluZGljYXRvcnMgd2l0aCBhYmJyZXZpYXRpb24gYW5kIG9uZSBjb3VudHJ5CgpgYGB7ciBjYWNoZT1UUlVFfQpjaG9zZW5faW5kaWNhdG9yXzEgPC0gIk5ZLkdEUC5ERUZMLktELlpHIgpzaG9ydF9uYW1lXzEgPC0gImdkcF9kZWZsYXRvciIKY2hvc2VuX2luZGljYXRvcl8yIDwtICJDUFRPVFNBWE5aR1kiCnNob3J0X25hbWVfMiA8LSAiY3BpX3ByaWNlIgpjaG9zZW5fY291bnRyeSA8LSAiVW5pdGVkIFN0YXRlcyIKV0RJKGNvdW50cnkgPSAiYWxsIiwgaW5kaWNhdG9yID0gYyhzaG9ydF9uYW1lXzEgPSBjaG9zZW5faW5kaWNhdG9yXzEsIHNob3J0X25hbWVfMiA9IGNob3Nlbl9pbmRpY2F0b3JfMiksIGV4dHJhPVRSVUUsIGNhY2hlPXdkaV9jYWNoZSkgJT4lIAogIGZpbHRlcihjb3VudHJ5ID09IGNob3Nlbl9jb3VudHJ5KSAlPiUgCiAgcGl2b3RfbG9uZ2VyKGMoc2hvcnRfbmFtZV8xLCBzaG9ydF9uYW1lXzIpLCBuYW1lc190byA9ICJjbGFzcyIsIHZhbHVlc190byA9ICJ2YWx1ZSIpICU+JSBkcm9wX25hKHZhbHVlKSAlPiUKICBnZ3Bsb3QoYWVzKHllYXIsIHZhbHVlLCBjb2wgPSBjbGFzcykpICsgZ2VvbV9saW5lKCkgKwogIGxhYnModGl0bGUgPSBwYXN0ZSgiV0RJICIsIGNob3Nlbl9pbmRpY2F0b3JfMSwgIjogIiwgc2hvcnRfbmFtZV8xLCAiXG4iLCBjaG9zZW5faW5kaWNhdG9yXzIsICI6ICIsIHNob3J0X25hbWVfMiwgIiAtICIsIGNob3Nlbl9jb3VudHJ5KSkgKwogIHNjYWxlX2NvbG9yX21hbnVhbChsYWJlbHMgPSBjKHNob3J0X25hbWVfMSwgc2hvcnRfbmFtZV8yKSwgdmFsdWVzID0gc2NhbGVzOjpodWVfcGFsKCkoMikpCmBgYAoKYGBge3IgY2FjaGU9VFJVRX0KY2hvc2VuX2luZGljYXRvcl8xIDwtICJTTC5UTEYuQ0FDVC5NQS5ORS5aUyIKc2hvcnRfbmFtZV8xIDwtICJtYWxlIgpjaG9zZW5faW5kaWNhdG9yXzIgPC0gIlNMLlRMRi5DQUNULkZFLk5FLlpTIgpzaG9ydF9uYW1lXzIgPC0gImZlbWFsZSIKY2hvc2VuX2NvdW50cnkgPC0gIlVuaXRlZCBTdGF0ZXMiCldESShjb3VudHJ5ID0gImFsbCIsIGluZGljYXRvciA9IGMoc2hvcnRfbmFtZV8xID0gY2hvc2VuX2luZGljYXRvcl8xLCBzaG9ydF9uYW1lXzIgPSBjaG9zZW5faW5kaWNhdG9yXzIpLCBleHRyYT1UUlVFLCBjYWNoZT13ZGlfY2FjaGUpICU+JSAKICBmaWx0ZXIoY291bnRyeSA9PSBjaG9zZW5fY291bnRyeSkgJT4lIAogIHBpdm90X2xvbmdlcihjKHNob3J0X25hbWVfMSwgc2hvcnRfbmFtZV8yKSwgbmFtZXNfdG8gPSAiY2xhc3MiLCB2YWx1ZXNfdG8gPSAidmFsdWUiKSAlPiUgZHJvcF9uYSh2YWx1ZSkgJT4lCiAgZ2dwbG90KGFlcyh5ZWFyLCB2YWx1ZSwgY29sID0gY2xhc3MpKSArIGdlb21fbGluZSgpICsKICBsYWJzKHRpdGxlID0gcGFzdGUoIldESSAiLCBjaG9zZW5faW5kaWNhdG9yXzEsICI6ICIsIHNob3J0X25hbWVfMSwgIlxuIiwgY2hvc2VuX2luZGljYXRvcl8yLCAiOiAiLCBzaG9ydF9uYW1lXzIsICIgLSAiLCBjaG9zZW5fY291bnRyeSkpICsKICBzY2FsZV9jb2xvcl9tYW51YWwobGFiZWxzID0gYyhzaG9ydF9uYW1lXzEsIHNob3J0X25hbWVfMiksIHZhbHVlcyA9IHNjYWxlczo6aHVlX3BhbCgpKDIpKQpgYGAKCiMjIyMg44GE44GP44Gk44GL44Gu5Zu944Gr44Gk44GE44Gm44Gu44CB5LqM44Gk44Gu5oyH5qiZ77yIV0RJ77yJ44Go44CB44Gd44Gu55Wl56ew44GL44KJ44CB5oqY57ea44Kw44Op44OV44KS5L2c5oiQCgpMaW5lIFBsb3Qgd2l0aCB0d28gaW5kaWNhdG9ycyB3aXRoIGFiYnJldmlhdGlvbiBhbmQgc2V2ZXJhbCBjb3VudHJpZXMKCmBgYHtyIGNhY2hlPVRSVUV9CmNob3Nlbl9pbmRpY2F0b3JfMSA8LSAiTlkuR0RQLkRFRkwuS0QuWkciCnNob3J0X25hbWVfMSA8LSAiZ2RwX2RlZmxhdG9yIgpjaG9zZW5faW5kaWNhdG9yXzIgPC0gIkNQVE9UU0FYTlpHWSIKc2hvcnRfbmFtZV8yIDwtICJjcGlfcHJpY2UiCmNob3Nlbl9jb3VudHJpZXMgPC0gYygiVW5pdGVkIFN0YXRlcyIsICJGcmFuY2UiLCAiSmFwYW4iKQpXREkoY291bnRyeSA9ICJhbGwiLCBpbmRpY2F0b3IgPSBjKHNob3J0X25hbWVfMSA9IGNob3Nlbl9pbmRpY2F0b3JfMSwgc2hvcnRfbmFtZV8yID0gY2hvc2VuX2luZGljYXRvcl8yKSwgZXh0cmE9VFJVRSwgY2FjaGU9d2RpX2NhY2hlKSAlPiUgCiAgZmlsdGVyKGNvdW50cnkgJWluJSBjaG9zZW5fY291bnRyaWVzKSAlPiUgCiAgcGl2b3RfbG9uZ2VyKGMoc2hvcnRfbmFtZV8xLCBzaG9ydF9uYW1lXzIpLCBuYW1lc190byA9ICJjbGFzcyIsIHZhbHVlc190byA9ICJ2YWx1ZSIpICU+JSBkcm9wX25hKHZhbHVlKSAlPiUKICBnZ3Bsb3QoYWVzKHllYXIsIHZhbHVlLCBsaW5ldHlwZSA9IGNsYXNzLCBjb2wgPSBjb3VudHJ5KSkgKyBnZW9tX2xpbmUoKSArCiAgbGFicyh0aXRsZSA9IHBhc3RlKCJXREkgIiwgY2hvc2VuX2luZGljYXRvcl8xLCAiOiAiLCBzaG9ydF9uYW1lXzEsICJcbiIsIGNob3Nlbl9pbmRpY2F0b3JfMiwgIjogIiwgc2hvcnRfbmFtZV8yKSkgKwogIHNjYWxlX2xpbmV0eXBlX21hbnVhbChsYWJlbHMgPSBjKHNob3J0X25hbWVfMSwgc2hvcnRfbmFtZV8yKSwgdmFsdWVzID0gYygic29saWQiLCAiZGFzaGVkIikpCmBgYAoKCmBgYHtyIGNhY2hlPVRSVUV9CmNob3Nlbl9pbmRpY2F0b3JfMSA8LSAiU0wuVExGLkNBQ1QuTUEuTkUuWlMiCnNob3J0X25hbWVfMSA8LSAibWFsZSIKY2hvc2VuX2luZGljYXRvcl8yIDwtICJTTC5UTEYuQ0FDVC5GRS5ORS5aUyIKc2hvcnRfbmFtZV8yIDwtICJmZW1hbGUiCmNob3Nlbl9jb3VudHJpZXMgPC0gYygiVW5pdGVkIFN0YXRlcyIsICJGcmFuY2UiLCAiSmFwYW4iKQpXREkoY291bnRyeSA9ICJhbGwiLCBpbmRpY2F0b3IgPSBjKHNob3J0X25hbWVfMSA9IGNob3Nlbl9pbmRpY2F0b3JfMSwgc2hvcnRfbmFtZV8yID0gY2hvc2VuX2luZGljYXRvcl8yKSwgZXh0cmE9VFJVRSwgY2FjaGU9d2RpX2NhY2hlKSAlPiUgCiAgZmlsdGVyKGNvdW50cnkgJWluJSBjaG9zZW5fY291bnRyaWVzKSAlPiUgCiAgcGl2b3RfbG9uZ2VyKGMoc2hvcnRfbmFtZV8xLCBzaG9ydF9uYW1lXzIpLCBuYW1lc190byA9ICJjbGFzcyIsIHZhbHVlc190byA9ICJ2YWx1ZSIpICU+JSBkcm9wX25hKHZhbHVlKSAlPiUKICBnZ3Bsb3QoYWVzKHllYXIsIHZhbHVlLCBsaW5ldHlwZSA9IGNsYXNzLCBjb2wgPSBjb3VudHJ5KSkgKyBnZW9tX2xpbmUoKSArCiAgbGFicyh0aXRsZSA9IHBhc3RlKCJXREkgIiwgY2hvc2VuX2luZGljYXRvcl8xLCAiOiAiLCBzaG9ydF9uYW1lXzEsICJcbiIsIGNob3Nlbl9pbmRpY2F0b3JfMiwgIjogIiwgc2hvcnRfbmFtZV8yKSkgKwogIHNjYWxlX2xpbmV0eXBlX21hbnVhbChsYWJlbHMgPSBjKHNob3J0X25hbWVfMSwgc2hvcnRfbmFtZV8yKSwgdmFsdWVzID0gYygic29saWQiLCAiZGFzaGVkIikpCmBgYAoKIyMg6Kqy6aGM44CAQXNzaWdubWVudAoK5LiK44Gu44OG44Oz44OX44Os44O844OI44KS44Kz44OU44O844GX44Gm44CB5LiL44Gr6LK844KK5LuY44GR44CB5oyH5qiZIGBpbmRpY2F0b3JgIOOBqOOAgeeVpeensCBgc2hvcnRfbmFtZWAg44Go44CB44GE44GP44Gk44GL44Gu5Zu95ZCNIGBjaG9zZW5fY291bnRyaWVzYCDjgpLjgIHlhaXjgozmm7/jgYjjgabjgIHoqabjgZfjgabjgb/jgabjgY/jgaDjgZXjgYTjgIIKCgojIERBWSAy77yaMuaciDIy5pelCgojIyDmjqLntKLnmoTjg4fjg7zjgr/op6PmnpDjgIBFeHBsb3JhdG9yeSBEYXRhIEFuYWx5c2lzIChFREEpCgojIyMg5o6i57Si55qE44OH44O844K/6Kej5p6Q44Go44Gv77yfIChbUG9zaXQgUHJpbWVyc10oaHR0cHM6Ly9wb3NpdC5jbG91ZC9sZWFybi9wcmltZXJzLzMuMSkpCgoxLiBFREHjga/jgIHjg4fjg7zjgr/jgYzkvZXjgpLoqp7jgaPjgabjgYTjgovjgYvjgpLnkIbop6PjgZnjgovjgZ/jgoHjga7lj43lvqnnmoTjgarjgrXjgqTjgq/jg6vjgafjgZnjgIIKCjIuIOOBvuOBmuOAgeODh+ODvOOCv+OBq+mWouOBmeOCi+WVj+OBhOOCkuS9nOaIkOOBl+OBvuOBmeOAggoKMy4g44OH44O844K/44Gu5Y+v6KaW5YyW44CB5aSJ5o+b44CB44Oi44OH44Oq44Oz44Kw44KS6KGM44GE44CB562U44GI44KS5o6i44GX44G+44GZ44CCCgrlrabnv5LjgZfjgZ/jgZPjgajjgpLmtLvnlKjjgZfjgabjgIHllY/jgYTjgpLkv67mraPjgZfjgZ/jgorjgIHmlrDjgZfjgYTllY/jgYTjgpLogIPjgYjjgZ/jgorjgZfjgb7jgZnjgILjgZ3jgZfjgabjgIHjgZPjga7jgrXjgqTjgq/jg6vjgpLnubDjgorov5TjgZfjgabjgYTjgY3jgb7jgZnjgIIKCkVEQeOBr+ODh+ODvOOCv+WIhuaekOOBq+OBiuOBhOOBpumHjeimgeOBquW9ueWJsuOCkuaenOOBn+OBl+OBvuOBmeOAguOBvuOBn+OAgeODh+ODvOOCv+OBruWTgeizquOCkuS/neiovOOBmeOCi+OBn+OCgeOBq+OAgeODh+ODvOOCv+OBruizquOCkueiuuiqjeOBmeOCi+OBn+OCgeOBq+S9v+eUqOOBmeOCi+OBk+OBqOOCguOBp+OBjeOBvuOBmeOAggoKIVtSNERTIOOBi+OCieOBruOCpOODoeODvOOCuF0oZGF0YS9kYXRhLXNjaWVuY2UucG5nKQoKIyMjIOODh+ODvOOCv+OBruWPluW+l+ODu+iqreOBv+i+vOOBvyAtIEltcG9ydGluZyBEYXRhCgrjgrnjgr/jg7zjg4jjga/jgIHmnKzmnaXjga/jgIHjg4fjg7zjgr/jga7kvZzmiJDjg7vmjqLntKLjgafjgZnjgYzjgIHjgZnjgafjgavjgIHliIbmnpDjgZfjgZ/jgYTjg4fjg7zjgr/jga/jgZnjgafjgavjgYLjgovjgajjgZfjgaboqbHjgpLpgLLjgoHjgb7jgZnjgILjgb7jgZrjga/jgIFgZGF0YWAg44OV44Kp44Or44OA77yIZGlyZWN0b3J577yJ44KS5L2c5oiQ44GX44Gm44GK44GP44Go6Imv44GE44CC5Y+z5LiL44Gu56qT5p6g44GuIEZpbGVzIOOCv+ODluOBi+OCieOAgU5ldyBGb2xkZXIg44Gn5L2c5oiQ44GX44Gm44KC44KI44GE44CCCgpgYGB7ciBldmFsPUZBTFNFfQpkaXIuY3JlYXRlKCIuL2RhdGEiKQpgYGAKCgrjg4fjg7zjgr/jga7lj5blvpfjg7voqq3jgb/ovrzjgb/jgpLjgIHlm5vjgaTjga7mlrnms5XjgavliIbjgZHjgaboqqzmmI7jgZfjgb7jgZnjgIIKCjEuIOODkeODg+OCseODvOOCuOOBruWIqeeUqAogIC0g5L6L77yaV0RJIOOBquOBqeOAguS9leW6puOCguOAgeODgOOCpuODs+ODreODvOODieOBl+OBquOBj+OBpuiJr+OBhOOCiOOBhOOBq+OAgeabuOOBjeWHuuOBl+OBpuOBiuOBjeOAgTIg44KS5L2/44GG44Go44KI44GE44CCYHdyaXRlKGRmX25hbWUsICIuL2RhdGEvbmFtZS5jc3YiKWAKMi4g44Kz44Oz44OU44Ol44O844K/5LiK44Gr44GC44KLIENTViDjgarjganjga7jg4bjgq3jgrnjg4jjg5XjgqHjgqTjg6vjgpLoqq3jgb/ovrzjgoAKICAtIOS+i++8mmBkZl9uYW1lIDwtIHJlYWRfY3N2KCIuL2RhdGEvZmlsZV9uYW1lLmNzdiIpYAozLiDjgqTjg7Pjgr/jg7zjg43jg4Pjg4jkuIrjga7jg4fjg7zjgr/jga7jgqLjg4njg6zjgrnvvIhVUkzvvInjgpLkvb/jgaPjgabjgIFDU1Yg44Gq44Gp44Gu44OG44Kt44K544OI44OV44Kh44Kk44Or44KS6Kqt44G/6L6844KA44CCCiAgLSDkvovvvJpgZGZfbmFtZSA8LSByZWFkX2Nzdih1cmxfb2ZfYV9jc3YpYAo0LiDjgrPjg7Pjg5Tjg6Xjg7zjgr/kuIrjgavjgYLjgovjgIFFeGNlbCDjg5XjgqHjgqTjg6vjgarjganjga7jg4fjgrjjgr/jg6vjg5XjgqHjgqTjg6vjgpLoqq3jgb/ovrzjgoDjgILjgb7jgZrjgIFgbGlicmFyeShyZWFkeGwpYOOAggogIC0g5L6L77yaYGRmX25hbWUgPC0gcmVhZF9leGNlbCgiLi9kYXRhL2ZpbGVfbmFtZS54bHN4IilgCjUuIOOCteOCpOODiOOBi+OCieODgOOCpuODs+ODreODvOODieOBl+OBpuOAgVByb2plY3Qg44Gu44OH44O844K/44OV44Kp44Or44OA44Gr56e744GZ44CC44G+44Gf44Gv44CB44OH44O844K/44Gu44Ki44OJ44Os44K577yIVVJM77yJ44GM44KP44GL44Gj44Gm44GE44KM44Gw44CB55u05o6l44OA44Km44Oz44Ot44O844OJ44CCCiAgLSDkvovvvJpgZG93bmxvYWQuZmlsZSh1cmxfb2ZfYV9kYXRhLCBkZXN0ZmlsZSA9ICIuL2RhdGEvZGF0YV9uYW1lIikKNi4g44Kv44Oq44OD44OX44Oc44O844OJ44Gr44Kz44OU44O844GX44Gm6Kqt44G/6L6844KA44CCCiAgLSDkvovvvJpgZGZfbmFtZSA8LSByZWFkX2RlbGltKGNsaXBib2FyZCgpKWAKCiMjIyBgV0RJY2FjaGUoKWAg44Gu5omx44GECgrkuozjgaTjga7jgIHjg5XjgqHjgqTjg6vjgYzkuIDjgaTjgavjgarjgaPjgZ/jgIHjg6rjgrnjg4jjgafjgYLjgovjgZ/jgoHjgIHpgZXjgaPjgablkb3ku6TjgpLkvb/jgYTjgb7jgZnjgIIKCmBgYHtyfQp3ZGlfY2FjaGUgPC0gV0RJY2FjaGUoKQp3cml0ZV9yZHMod2RpX2NhY2hlLCAiLi93ZGlfY2FjaGUuUkRhdGEiKQpgYGAKCmBgYHtyfQp3ZGlfY2FjaGUgPC0gcmVhZF9yZHMoIi4vd2RpX2NhY2hlLlJEYXRhIikKYGBgCgojIyMg5Zu96Zqb5qmf6Zai44Gu44OH44O844K/IEludGVybmF0aW9uYWwgSW5zdGl0dXRpb25zJyBEYXRhCgotIFdvcmxkIEJhbms6IGh0dHBzOi8vZGF0YS53b3JsZGJhbmsub3JnCi0gVU4gRGF0YTogaHR0cHM6Ly9kYXRhLnVuLm9yZwotIE9FQ0Q6IGh0dHBzOi8vZGF0YS5vZWNkLm9yZy8KCmBgYHtyfQp1cmxfdW5fcG9wIDwtICJodHRwczovL2RhdGEudW4ub3JnL19Eb2NzL1NZQi9DU1YvU1lCNjVfMV8yMDIyMDlfUG9wdWxhdGlvbiwlMjBTdXJmYWNlJTIwQXJlYSUyMGFuZCUyMERlbnNpdHkuY3N2IgpkZl91bl9wb3AwIDwtIHJlYWRfY3N2KHVybF91bl9wb3ApCmRmX3VuX3BvcDAKYGBgCgpgYGB7cn0KdXJsX3VuX3BvcCA8LSAiaHR0cHM6Ly9kYXRhLnVuLm9yZy9fRG9jcy9TWUIvQ1NWL1NZQjY1XzFfMjAyMjA5X1BvcHVsYXRpb24sJTIwU3VyZmFjZSUyMEFyZWElMjBhbmQlMjBEZW5zaXR5LmNzdiIKZGZfdW5fcG9wIDwtIHJlYWRfY3N2KHVybF91bl9wb3AsIHNraXA9MSkKZGZfdW5fcG9wCmBgYAoKYGBge3J9CmRmX3VuX3BvcCAlPiUgZGlzdGluY3QoYFJlZ2lvbi9Db3VudHJ5L0FyZWFgLCBgLi4uMmApCmBgYAoKCmBgYHtyfQpkZl91bl9wb3AgJT4lIGZpbHRlcihgUmVnaW9uL0NvdW50cnkvQXJlYWAgJWluJSBjKDIsMTksMTQyLDE1MCw5KSwgU2VyaWVzID09ICJQb3B1bGF0aW9uIG1pZC15ZWFyIGVzdGltYXRlcyAobWlsbGlvbnMpIikgJT4lCiAgZ2dwbG90KGFlcyhZZWFyLCBWYWx1ZSwgZmlsbCA9IGAuLi4yYCkpICsgZ2VvbV9hcmVhKGNvbD0iYmxhY2siKSArCiAgbGFicyh0aXRsZSA9ICJQb3B1bGF0aW9uIG1pZC15ZWFyIGVzdGltYXRlcyAobWlsbGlvbnMpIG9mIHRoZSBXb3JsZCIpCmBgYAoKIyMgT0VDRCBkYXRhCgotIGh0dHBzOi8vZGF0YS5vZWNkLm9yZy8KCi0gW+aXpeacrOOBruaZgumWk+W9k+OBn+OCiueUn+eUo+aAp+OBr09FQ0QzOOOCq+WbveS4rTI35L2N77yI5pel5pys55Sf55Sj5oCn5pys6YOo44CM5Yq05YON55Sf55Sj5oCn44Gu5Zu96Zqb5q+U6LyD44CN77yJXShodHRwczovL3d3dy5qY2NpLm9yLmpwL25ld3MvdHJlbmQtYm94LzIwMjIvMTIxOTE1NDcxMy5odG1sKQogIC0gW+WKtOWDjeeUn+eUo+aAp+OBruWbvemam+avlOi8gzIwMjJdKGh0dHBzOi8vd3d3LmpwYy1uZXQuanAvcmVzZWFyY2gvZGV0YWlsLzAwNjE3NC5odG1sKQotIFtQcm9kdWN0aXZpdHkgc3RhdGlzdGljc10oaHR0cHM6Ly93d3cub2VjZC5vcmcvc2RkL3Byb2R1Y3Rpdml0eS1zdGF0cy8pCiAgLSBbUmVhZCBNb3JlOiBJbXByb3ZpbmcgUHJvZHVjdGl2aXR5IE1lYXN1cmVtZW50IFByYWN0aWNlc10oaHR0cHM6Ly93d3cub2VjZC5vcmcvc2RkL3Byb2R1Y3Rpdml0eS1zdGF0cy9pbXByb3ZpbmctcHJvZHVjdGl2aXR5LW1lYXN1cmVtZW50LXByYWN0aWNlcy5odG0pCiAgICAtIFtMZXZlbCBvZiBHRFAgcGVyIGNhcGl0YSBhbmQgcHJvZHVjdGl2aXR5XShodHRwczovL3N0YXRzLm9lY2Qub3JnL0luZGV4LmFzcHg/RGF0YVNldENvZGU9UERCX0xWKQogICAgLSBbR0RQIHBlciBob3VyIHdvcmtlZF0oaHR0cHM6Ly9kYXRhLm9lY2Qub3JnL2xwcmR0eS9nZHAtcGVyLWhvdXItd29ya2VkLmh0bSNpbmRpY2F0b3ItY2hhcnQpCiAgICAKICAgIAojIyMgRGVmaW5pdGlvbiBvZiBHRFAgcGVyIGhvdXIgd29ya2VkCgpHRFAgcGVyIGhvdXIgd29ya2VkIGlzIGEgbWVhc3VyZSBvZiBsYWJvdXIgcHJvZHVjdGl2aXR5LiBJdCBtZWFzdXJlcyBob3cgZWZmaWNpZW50bHkgbGFib3VyIGlucHV0IGlzIGNvbWJpbmVkIHdpdGggb3RoZXIgZmFjdG9ycyBvZiBwcm9kdWN0aW9uIGFuZCB1c2VkIGluIHRoZSBwcm9kdWN0aW9uIHByb2Nlc3MuIExhYm91ciBpbnB1dCBpcyBkZWZpbmVkIGFzIHRvdGFsIGhvdXJzIHdvcmtlZCBvZiBhbGwgcGVyc29ucyBlbmdhZ2VkIGluIHByb2R1Y3Rpb24uIExhYm91ciBwcm9kdWN0aXZpdHkgb25seSBwYXJ0aWFsbHkgcmVmbGVjdHMgdGhlIHByb2R1Y3Rpdml0eSBvZiBsYWJvdXIgaW4gdGVybXMgb2YgdGhlIHBlcnNvbmFsIGNhcGFjaXRpZXMgb2Ygd29ya2VycyBvciB0aGUgaW50ZW5zaXR5IG9mIHRoZWlyIGVmZm9ydC4gVGhlIHJhdGlvIGJldHdlZW4gdGhlIG91dHB1dCBtZWFzdXJlIGFuZCB0aGUgbGFib3VyIGlucHV0IGRlcGVuZHMgdG8gYSBsYXJnZSBkZWdyZWUgb24gdGhlIHByZXNlbmNlIGFuZC9vciB1c2Ugb2Ygb3RoZXIgaW5wdXRzIChlLmcuIGNhcGl0YWwsIGludGVybWVkaWF0ZSBpbnB1dHMsIHRlY2huaWNhbCwgb3JnYW5pc2F0aW9uYWwgYW5kIGVmZmljaWVuY3kgY2hhbmdlLCBlY29ub21pZXMgb2Ygc2NhbGUpLiBUaGlzIGluZGljYXRvciBpcyBtZWFzdXJlZCBpbiBVU0QgKGNvbnN0YW50IHByaWNlcyAyMDEwIGFuZCBQUFBzKSBhbmQgaW5kaWNlcy4KCuWKtOWDjeaZgumWk+W9k+OBn+OCikdEUOOBr+OAgeWKtOWDjeeUn+eUo+aAp+OBruaMh+aomeOBp+OBguOCi+OAguOBk+OCjOOBr+OAgeWKtOWDjeaKleWFpemHj+OBjOS7luOBrueUn+eUo+imgee0oOOBqOe1hOOBv+WQiOOCj+OBleOCjOOAgeeUn+eUo+ODl+ODreOCu+OCueOBp+OBqeOCjOOBoOOBkeWKueeOh+eahOOBq+WIqeeUqOOBleOCjOOBn+OBi+OCkua4rOWumuOBmeOCi+OCguOBruOBp+OBguOCi+OAguWKtOWDjeaKleWFpemHj+OBr+OAgeeUn+eUo+OBq+W+k+S6i+OBmeOCi+OBmeOBueOBpuOBruS6uuOBrue3j+WKtOWDjeaZgumWk+OBqOOBl+OBpuWumue+qeOBleOCjOOCi+OAguWKtOWDjeeUn+eUo+aAp+OBr+OAgeWKtOWDjeiAheOBruWAi+S6uueahOiDveWKm+OChOWKquWKm+OBruW8t+OBleOBqOOBhOOBo+OBn+WKtOWDjeOBrueUn+eUo+aAp+OCkumDqOWIhueahOOBq+OBl+OBi+WPjeaYoOOBl+OBpuOBhOOBquOBhOOAguOCouOCpuODiOODl+ODg+ODiOaMh+aomeOBqOWKtOWDjeaKleWFpemHj+OBruavlOeOh+OBr+OAgeS7luOBruaKleWFpeeJqe+8iOizh+acrOOAgeS4remWk+aKleWFpeeJqeOAgeaKgOihk+ODu+e1hOe5lOODu+WKueeOh+OBruWkieWMluOAgeimj+aooeOBrue1jOa4iOOBquOBqe+8ieOBruWtmOWcqOOChOWIqeeUqOOBq+Wkp+OBjeOBj+W3puWPs+OBleOCjOOCi+OAguOBk+OBruaMh+aomeOBr+OAgeexs+ODieODq++8iDIwMTDlubTjga7mgZLluLjkvqHmoLzjgYrjgojjgbNQUFDvvInjgYrjgojjgbPmjIfmqJnjgafmuKzlrprjgZXjgozjgabjgYTjgb7jgZnjgIIKCmBgYHtyfQpkZl9vZWNkX3Byb2R1Y3Rpdml0eSA8LSByZWFkX2NzdigiLi9kYXRhL0RQX0xJVkVfMjEwMjIwMjMxMTE3MTIwNjUuY3N2IikKZGZfb2VjZF9wcm9kdWN0aXZpdHkKYGBgCgpgYGB7cn0KZGZfb2VjZF9wcm9kdWN0aXZpdHkkTE9DQVRJT04gJT4lIHVuaXF1ZSgpCmBgYApgYGB7cn0KZGZfb2VjZF9wcm9kdWN0aXZpdHkkSU5ESUNBVE9SICU+JSB1bmlxdWUoKQpgYGAKCmBgYHtyfQpkZl9vZWNkX3Byb2R1Y3Rpdml0eSRTVUJKRUNUICU+JSB1bmlxdWUoKQpgYGAKCmBgYHtyfQpkZl9vZWNkX3Byb2R1Y3Rpdml0eSRNRUFTVVJFICU+JSB1bmlxdWUoKQpgYGAKCmBgYHtyfQpkZl9vZWNkX3Byb2R1Y3Rpdml0eSRGUkVRVUVOQ1kgJT4lIHVuaXF1ZSgpCmBgYAoKYGBge3J9CmRmX29lY2RfcHJvZHVjdGl2aXR5JFRJTUUgJT4lIHVuaXF1ZSgpCmBgYAoKYGBge3J9CmRmX29lY2RfcHJvZHVjdGl2aXR5ICU+JSAKICBmaWx0ZXIoTUVBU1VSRSA9PSAiVVNEIiwgVElNRSA9PSAyMDIxKSAlPiUKICBzZWxlY3QoTE9DQVRJT04sIFZhbHVlKSAlPiUKICBhcnJhbmdlKGRlc2MoVmFsdWUpKQpgYGAKYGBge3J9CmRmX29lY2RfcHJvZHVjdGl2aXR5ICU+JSAKICBmaWx0ZXIoTE9DQVRJT04gJWluJSBjKCJKUE4iLCAiT0VDRCIsICJHLTciLCAiRVUyOCIpKSAlPiUKICBmaWx0ZXIoTUVBU1VSRSA9PSAiVVNEIikgJT4lCiAgZ2dwbG90KGFlcyhUSU1FLCBWYWx1ZSwgY29sID0gTE9DQVRJT04pKSArIGdlb21fbGluZSgpICsgCiAgbGFicyh0aXRsZT0iR0RQIHBlciBob3VyIHdvcmtlZCIsIHN1YnRpdGxlPSJUb3RhbCwgMjAxNT0xMDAsIDIwMjEgb3IgbGF0ZXN0IGF2YWlsYWJsZSIpCmBgYAoKCiMjIyBFZHVjYXRpb24KCkFkdWx0IGVkdWNhdGlvbiBsZXZlbDogaHR0cHM6Ly9kYXRhLm9lY2Qub3JnL2VkdWF0dC9hZHVsdC1lZHVjYXRpb24tbGV2ZWwuaHRtCgpgYGB7cn0KZGZfb2VjZF9lZHVjYXRpb25fbGV2ZWwgPC0gcmVhZF9jc3YoIi4vZGF0YS9EUF9MSVZFXzIxMDIyMDIzMTIwMTMyNjU0LmNzdiIpCmRmX29lY2RfZWR1Y2F0aW9uX2xldmVsCmBgYAoKIyMgV29ybGQgSW5lcXVhbGl0eSBSZXBvcnQgMjAyMgoKCgpgYGB7cn0KbGlicmFyeShyZWFkeGwpCmBgYAoKCmBgYHtyfQp1cmxfc3VtbWFyeSA8LSAiaHR0cHM6Ly93aXIyMDIyLndpZC53b3JsZC93d3ctc2l0ZS91cGxvYWRzLzIwMjIvMDMvV0lSMjAyMlRhYmxlc0ZpZ3VyZXMtU3VtbWFyeS54bHN4Igpkb3dubG9hZC5maWxlKHVybCA9IHVybF9zdW1tYXJ5LCBkZXN0ZmlsZSA9ICIuL2RhdGEvV0lSMjAyMnMueGxzeCIsIG1vZGUgPSAid2IiKSAKYGBgCgpgYGB7cn0KZXhjZWxfc2hlZXRzKCIuL2RhdGEvV0lSMjAyMnMueGxzeCIpCmBgYApgYGB7cn0KZGYxX3dpciA8LSByZWFkX2V4Y2VsKCIuL2RhdGEvV0lSMjAyMnMueGxzeCIsIHNoZWV0ID0gImRhdGEtRjEiKQpkZjFfd2lyCmBgYApgYGB7cn0KZGYxX3dpciAlPiUgc2VsZWN0KGNhdCA9IC4uLjEsIDI6NCkgJT4lCiAgcGl2b3RfbG9uZ2VyKDI6NCwgbmFtZXNfdG8gPSAiZ3JvdXAiLCB2YWx1ZXNfdG8gPSAidmFsdWUiKSAlPiUKICBnZ3Bsb3QoYWVzKHggPSBjYXQsIHkgPSB2YWx1ZSwgZmlsbCA9IGdyb3VwKSkgKwogIGdlb21fY29sKHBvc2l0aW9uID0gImRvZGdlIikgKyAKICBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWxzID0gc2NhbGVzOjpwZXJjZW50X2Zvcm1hdChhY2N1cmFjeSA9IDEpKSArIAogIGdlb21fdGV4dChhZXMoeCA9IGNhdCwgeSA9IHZhbHVlLCBncm91cCA9IGdyb3VwLCBsYWJlbCA9IHNjYWxlczo6bGFiZWxfcGVyY2VudChhY2N1cmFjeT0xKSh2YWx1ZSkpLCB2anVzdCA9IC0wLjA4LAogICAgICAgICAgICBwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKDAuOSkpICsgCiAgbGFicyh0aXRsZSA9ICJGaWd1cmUgMS4gR2xvYmFsIGluY29tZSBhbmQgd2VhbHRoIGluZXF1YWxpdHksIDIwMjEiLAogICAgICAgeCA9ICIiLCB5ID0gIlNoYXJlIG9mIHRvdGFsIGluY29tZSBvciB3ZWFsdGgiLCBmaWxsID0gIiIpCmBgYAoKYGBge3J9CmRmMl93aXIgPC0gcmVhZF9kZWxpbShjbGlwYm9hcmQoKSkKZGYyX3dpciAKYGBgCgpgYGB7cn0KZGYyX3dpcjIgPC0gcmVhZF9leGNlbCgiLi9kYXRhL1dJUjIwMjJzLnhsc3giLCBzaGVldCA9ICJkYXRhLUYyIikKZGYyX3dpcjIKYGBgCgpgYGB7cn0KZGYyX3dpcjIgJT4lIHBpdm90X2xvbmdlcigzOjUsIG5hbWVzX3RvID0gImxldmVsIiwgdmFsdWVzX3RvID0gInZhbHVlIikgJT4lCiAgZ2dwbG90KGFlcyh4ID0gaXNvLCB5ID0gdmFsdWUsIGZpbGwgPSBsZXZlbCkpICsKICBnZW9tX2NvbChwb3NpdGlvbiA9ICJkb2RnZSIpICsgCiAgc2NhbGVfeF9kaXNjcmV0ZShsYWJlbHMgPSBmdW5jdGlvbih4KSBzdHJpbmdyOjpzdHJfd3JhcCh4LCB3aWR0aCA9IDgpKSArCiAgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscyA9IHNjYWxlczo6cGVyY2VudF9mb3JtYXQoYWNjdXJhY3kgPSAxKSkgKwogIGxhYnModGl0bGUgPSAiRmlndXJlIDIuIFRoZSBwb29yZXN0IGhhbGYgbGFncyBiZWhpbmQgQm90dG9tIDUwJSwgbWlkZGxlIDQwJSBcbmFuZCB0b3AgMTAlIGluY29tZSBzaGFyZXMgYWNyb3NzIHRoZSB3b3JsZCBpbiAyMDIxIiwKICAgICAgIHggPSAiIiwgeSA9ICJTaGFyZSBvZiBuYXRpb25hbCBpbmNvbWUgKCUpIiwgZmlsbCA9ICIiKQpgYGAKCiMjIyMgV0lSMjAyMjogaHR0cHM6Ly9kcy1zbC5naXRodWIuaW8vZGF0YS1hbmFseXNpcy93aXIyMDIyLm5iLmh0bWwKCiMjIyMgUmVmZXJlbmNlcwoKKiBDaGVhdCBTaGVldCAtIGByZWFkcmAKKiBbcmVhZHJdKGh0dHBzOi8vcmVhZHIudGlkeXZlcnNlLm9yZykKKiBbcmVhZHhsXShodHRwczovL3JlYWR4bC50aWR5dmVyc2Uub3JnKQoKCgoKIyMjIEVEQSBieSBSIFN0dWRpbzogU3RlcCA0IC0gRGF0YSBUcmFzbmZvcm1hdGlvbgoKNC4xLiBMb29rIGF0IHRoZSBkYXRhOiBzdXBwb3NlIGBkZmAgaXMgdGhlIGRhdGEgZnJhbWUKCiAgKiBJdCBpcyBhIGdvb2Qgb3B0aW9uIHRvIGNoYW5nZSBpbnRvIGEgdGliYmxlOiBgZHQgPC0gYXNfdGliYmxlKGRmKWAKICAqIGBoZWFkKGRmKWAsIGBzdHIoZGYpYCwgYHN1bW1hcnkoZGYpYCwgYGR0YCwgYGdsaW1wc2UoZHQpYAoKNC4yLiBMb29rIGF0IGVhY2ggdmFyaWFibGUKCiAgKiBjYXRlZ29yaWNhbD8gbnVtZXJpY2FsPyAKICAqIGZhY3Rvcj8gLSBbZm9yY2F0c10oaHR0cHM6Ly9mb3JjYXRzLnRpZHl2ZXJzZS5vcmcpCiAgCjQuMy4gVmFyaWF0aW9uIG9mIGVhY2ggZGF0YTogc3VwcG9zZSBgeDFgIGlzIGEgY29sdW1uIG5hbWUuCgogICogYGRmICU+JSBnZ3Bsb3QoKSArIGdlb21faGlzdG9ncmFtKGFlcyh4MSksIGJpbnMgPSAzMClgCiAgKiBgZGYgJT4lIGRyb3BfbmEoeDEpYDogc2VlIHRoZSByb3dzIHdpdGggYSB2YWx1ZSBpbiBgeDFgLiBJZiB0aGUgdmFsdWUgaXMgTkEsIHRoZSByb3cgaXMgbm90IHNob3duLgogIAogICAgLSBgZGZfd29fbmEgPC0gZGYgJT4lIGRyb3BfbmEoeDEpYCBpZiB5b3Ugd2FudCB0byB1c2Ugb25seSB0aGUgcm93cyB3aXRob3V0IE5BIGluIGB4MWAKICAgIAoKCjQuNC4gVXNlIGBkcHlscmAgYW5kIGB0aWR5cmAgdG8gY2hhbmdlIGNvbHVtbiBuYW1lcywgdGlkeSBkYXRhLCBhbmQvb3Igc3VtbWFyaXplIGRhdGEKCiAgKiBgcmVuYW1lYCwgYHNlbGVjdGAsIGBmaWx0ZXJgLCBgYXJyYW5nZWAsIGBtdXRhdGVgLCBgcGl2b3RfbG9uZ2VyKClgLCBgcGl2b3Rfd2lkZXIoKWAsIGBncm91cF9ieWAgYW5kIGBzdW1tYXJpemVgCgoKIyMjIyBSZWZlcmVuY2VzCgoqIENoZWF0IFNoZWV0IC0gYGRwbHlyYCBhbmQgYHRpZHlyYAoqIFtkcGx5cl0oaHR0cHM6Ly9kcGx5ci50aWR5dmVyc2Uub3JnKQoqIFt0aWR5cl0oaHR0cHM6Ly90aWR5ci50aWR5dmVyc2Uub3JnKQoKCgojIyMgRURBIGJ5IFIgU3R1ZGlvOiBTdGVwIDUgLSBWaXN1YWxpemUgRGF0YQoKNS4xLiBJbiBjb21iaW5hdGlvbiB3aXRoIFN0YXAgNCAtIGRhdGEgdHJhbnNmb3JtYXRpb24sIHRyeSB2YXJpb3VzIGRhdGEgdmlzdWFsaXphdGlvbi4KCiAgKiBXaGF0IHR5cGUgb2YgdmFyaWF0aW9uIG9jY3VycyB3aXRoaW4gbXkgdmFyaWFibGVzPwogICogV2hhdCB0eXBlIG9mIGNvdmFyaWF0aW9uIG9jY3VycyBiZXR3ZWVuIG15IHZhcmlhYmxlcz8KCgo1LjIuIEtlZXAgYSByZWNvcmQgb2Ygd2hhdCB5b3UgY2FuIG9ic2VydmUgYnkgdGhlIHZpc3VhbGl6YXRpb24KCjUuMy4gRWRpdCB0aGUgbGlzdCBvZiBxdWVzdGlvbnMgYnkgYWRkaW5nIG9yIHBvbGlzaGluZwoKNS40LiBTZWxlY3Qgc2V2ZXJhbCBpbmZvcm1hdGl2ZSBjaGFydCBhbmQgYWRkIG9wdGlvbnMKCjUuNS4gTG9vayBhdCBleGFtcGxlcyBmcm9tIHRoZSB0ZXh0Ym9va3Mgb3IgdGVhY2hpbmcgc2l0ZSB0byBoYXZlIGJldHRlciB2aXN1YWxpemF0aW9uCgoKIyMjIyBSZWZlcmVuY2VzCgoqIENoZWF0IFNoZWV0IC0gYGdncGxvdDJgIAoqIFtnZ3Bsb3QyXShodHRwczovL2dncGxvdDIudGlkeXZlcnNlLm9yZykKKiBbZ2dwbG90MiBib29rXShodHRwczovL2dncGxvdDItYm9vay5vcmcpCgojIyMgRURBIGJ5IFIgU3R1ZGlvOiBTdGVwIDYgLSBDb25jbHVzaW9ucyBhbmQgUXVlc3Rpb25zIGZvciBGdXJ0aGVyIFN0dWR5CgoxLiBFREEgaXMgYW4gaXRlcmF0aXZlIGN5Y2xlIHRoYXQgaGVscHMgeW91IHVuZGVyc3RhbmQgd2hhdCB5b3VyIGRhdGEgc2F5cy4gV2hlbiB5b3UgZG8gRURBLCB5b3U6CgoyLiBHZW5lcmF0ZSBxdWVzdGlvbnMgYWJvdXQgeW91ciBkYXRhCgozLiBTZWFyY2ggZm9yIGFuc3dlcnMgYnkgdmlzdWFsaXNpbmcsIHRyYW5zZm9ybWluZywgYW5kL29yIG1vZGVsaW5nIHlvdXIgZGF0YQoKVXNlIHdoYXQgeW91IGxlYXJuIHRvIHJlZmluZSB5b3VyIHF1ZXN0aW9ucyBhbmQvb3IgZ2VuZXJhdGUgbmV3IHF1ZXN0aW9ucwoKRURBIGlzIGFuIGltcG9ydGFudCBwYXJ0IG9mIGFueSBkYXRhIGFuYWx5c2lzLiBZb3UgY2FuIHVzZSBFREEgdG8gbWFrZSBkaXNjb3ZlcmllcyBhYm91dCB0aGUgd29ybGQ7IG9yIHlvdSBjYW4gdXNlIEVEQSB0byBlbnN1cmUgdGhlIHF1YWxpdHkgb2YgeW91ciBkYXRhLCBhc2tpbmcgcXVlc3Rpb25zIGFib3V0IHdoZXRoZXIgdGhlIGRhdGEgbWVldHMgeW91ciBzdGFuZGFyZHMgb3Igbm90LgoKCiMjIFRyYW5zZm9ybWluZyBEYXRhOiBgZHBseXJgLCBgdGlkeXJgCgojIyBWaXN1YWxpemluZyBEYXRhOiBgZ2dwbG90MmAKCi0gICBgZ2VvbV9zbW9vdGgoKWAKCiMjIFRlbXBsYXRlcwoKIyMgUHJhY3RpY3VtCgojIERBWSAz77yaMuaciDI05pelCgojIyBJbXBvcnRpbmcgRGF0YQoKCiMjIyMg5pel5pys6Kqe44OH44O844K/CgrlrabmoKHnqK7poZ7liKXpgLLlrabnjofjga7mjqjnp7s6IGh0dHBzOi8vZW1wb3dlcm1lbnQudHN1ZGEuYWMuanAvZGV0YWlsLzgyNTg0CgoKYGBge3J9CnVybF9zY2hvb2xfanAgPC0gImh0dHBzOi8vd3d3LmdlbmRlci5nby5qcC9hYm91dF9kYW5qby93aGl0ZXBhcGVyL3IwMi96ZW50YWkvaHRtbC9ob25wZW4vY3N2L3p1aHlvMDEtMDQtMDEuY3N2IgpndWVzc19lbmNvZGluZyh1cmxfc2Nob29sX2pwLCBuX21heCA9IDEwMDAwLCB0aHJlc2hvbGQgPSAwLjIpCmBgYAoKCmBgYHtyfQpkZl9zY2hvb2xfanAgPC0gcmVhZF9jc3YodXJsX3NjaG9vbF9qcCwgbG9jYWxlID0gbG9jYWxlKGVuY29kaW5nID0gIlNoaWZ0X0pJUyIpLCBza2lwPTIpCmRmX3NjaG9vbF9qcCAKYGBgCgpgYGB7ciB3YXJuaW5nPUZBTFNFfQpkZl9lZHUwIDwtIGRmX3NjaG9vbF9qcCAKY29sbmFtZXMoZGZfZWR1MCkgPC0gYygieWVhciIsICJoaWdoc2Nob29sX20iLCAiaGlnaHNjaG9vbF9mIiwgInZvY2F0aW9uYWxfbSIsICJ2b2NhdGlvbmFsX2YiLCAidW5pdmVyc2l0eV9tIiwgInVuaXZlcnNpdHlfZiIsICJqdW5pb3Jjb2xsZWdlX2YiLCAiZ3JhZHNjaG9vbF9tIiwgImdyYWRzY2hvb2xfZiIpCmRmX2VkdTAwIDwtIGRmX2VkdTAgJT4lIG11dGF0ZSh5ZWFyID0gMTk1MDoyMDE5LCAKICAgICAgICAgICAgICAgICAgIGhpZ2hzY2hvb2wgPSAoaGlnaHNjaG9vbF9tICsgaGlnaHNjaG9vbF9mKS8yLAogICAgICAgICAgICAgICAgICAgdm9jYXRpb25hbCA9ICh2b2NhdGlvbmFsX20gKyB2b2NhdGlvbmFsX2YpLzIsCiAgICAgICAgICAgICAgICAgICB1bml2ZXJzaXR5ID0gKHVuaXZlcnNpdHlfbSArIHVuaXZlcnNpdHlfZikvMiwgCiAgICAgICAgICAgICAgICAgICBqdW5pb3Jjb2xsZWdlID0ganVuaW9yY29sbGVnZV9mLAogICAgICAgICAgICAgICAgICAgZ3JhZHNjaG9vbCA9IChncmFkc2Nob29sX20gKyBncmFkc2Nob29sX2YpLzIpIApkZl9lZHUwMCAlPiUgZmlsdGVyKHllYXIgPj0gMTk1NCkgJT4lIHNlbGVjdCgtKDI6MTApKSAlPiUgCiAgcGl2b3RfbG9uZ2VyKDM6NSwgbmFtZXNfdG8gPSAic2Nob29scyIsIHZhbHVlc190byA9ICJwZXJjZW50YWdlIikgJT4lCiAgbXV0YXRlKHR5cGVzID0gZmFjdG9yKHNjaG9vbHMsIGxldmVscyA9IGMoInZvY2F0aW9uYWwiLCAianVuaW9yY29sbGVnZSIsICJ1bml2ZXJzaXR5IikpKSAlPiUKICBwaXZvdF9sb25nZXIoYyhoaWdoc2Nob29sLCBncmFkc2Nob29sKSwgbmFtZXNfdG8gPSAiaGlnaGdyYWQiLCB2YWx1ZXNfdG8gPSJ2YWx1ZSIpICU+JQogIG11dGF0ZShoaWdoX2dyYWQgPSBmYWN0b3IoaGlnaGdyYWQsIGxldmVscyA9IGMoImhpZ2hzY2hvb2wiLCAiZ3JhZHNjaG9vbCIpKSkgJT4lCiAgZ2dwbG90KCkgKwogIGdlb21fYXJlYShhZXMoeCA9IHllYXIsIHkgPSBwZXJjZW50YWdlLCBmaWxsID0gdHlwZXMpKSArCiAgZ2VvbV9saW5lKGFlcyh4ID0geWVhciwgeSA9IHZhbHVlLCBsaW5ldHlwZSA9IGhpZ2hfZ3JhZCkpICsgCiAgc2NhbGVfeF9jb250aW51b3VzKGJyZWFrcyA9IHJvdW5kKHNlcSgxOTYwLCAyMDIwLCBieSA9MTApLDEpKSArIAogIHNjYWxlX3lfY29udGludW91cyhicmVha3MgPSByb3VuZChzZXEoMCwgMTAwLCBieSA9MTApLDEpKSArIAogIGxhYnModGl0bGUgPSAiVGVydGlhbGx5IEVkdWNhdGlvbiBBZnRlciBIaWdoc2Nob29sIiwgCiAgICAgICBzdWJ0aXRsZSA9ICJ3aXRoIEhpZ2hzY2hvb2wgR3JhZHVhdGVzIGFuZCBHcmFkdWF0ZSBTY2hvb2wiLCBmaWxsID0gIiIsIGxpbmV0eXBlID0gIiIpCmBgYAoKCiMjIEV4cGxvcmF0b3J5IERhdGEgQW5hbHlzaXM7IFdvcmtmbG93CgojIyBUcmFuc2Zvcm1pbmcgRGF0YQoKLSAgIGBmaWx0ZXIoKWAsIGBzZWxlY3QoKWAsIGBhcnJhbmdlKClgLCBgbXV0YXRlKClgLCBgZ3JvdXBfYnkoKWAsIGBzdW1tYXJpemUoKWAKCiMjIFZpc3VhbGl6aW5nIERhdGEKClRoZXJlIGlzIG5vIHJ1bGUgYWJvdXQgd2hpY2ggcXVlc3Rpb25zIHlvdSBzaG91bGQgYXNrIHRvIGd1aWRlIHlvdXIgcmVzZWFyY2guIEhvd2V2ZXIsIHR3byB0eXBlcyBvZiBxdWVzdGlvbnMgd2lsbCBhbHdheXMgYmUgdXNlZnVsIGZvciBtYWtpbmcgZGlzY292ZXJpZXMgd2l0aGluIHlvdXIgZGF0YS4gWW91IGNhbiBsb29zZWx5IHdvcmQgdGhlc2UgcXVlc3Rpb25zIGFzOgoKLSAgIFdoYXQgdHlwZSBvZiB2YXJpYXRpb24gb2NjdXJzIHdpdGhpbiBteSB2YXJpYWJsZXM/CiAgICAtICAgVmFyaWFuY2UgLSBkaXN0cmlidXRpb24KLSAgIFdoYXQgdHlwZSBvZiBjb3ZhcmlhdGlvbiBvY2N1cnMgYmV0d2VlbiBteSB2YXJpYWJsZXM/CiAgICAtICAgQ292YXJpYW5jZSAtIGNvcnJlbGF0aW9uCgojIyBDb21iaW5pbmcgRGF0YQoKIyMgUHJhY3RpY3VtCgojIyBRdWVzdGlvbnMgYW5kIEFuc3dlcnMKCiMg5Y+C6ICDCgojIyBSTm90ZWJvb2sg44Gu5rS755SoCgrkuIvjga7jg6rjg7Pjgq/jgpLplovjgY3jgIHlj7PkuIrjga4gQ29kZSDjg5zjgr/jg7PjgYvjgonjgIFEb3dubG9hZCBSbWQg44KS6YG45oqe44GZ44KL44Go44CB44OA44Km44Oz44Ot44O844OJ44Gn44GN44G+44GZ44GL44KJ44CB44OA44Kk44Oz44Ot44O844OJ44GX44Gf44KC44Gu44KS44CB44OX44Ot44K444Kn44Kv44OI44O744OV44Kp44O844Or44OA44O844Gr56e75YuV44G+44Gf44Gv44Kz44OU44O844GX44Gm44GP44Gg44GV44GE44CC44OA44Km44Oz44Ot44O844OJ44Gn44GN44Gq44GE44Go44GN44Gv44CBQ3RybCDjgpLmirzjgZfjgarjgYzjgonjgIFEb3dubG9hZCBSbWQg44KS44Kv44Oq44OD44Kv44GZ44KL44Go44CBU2F2ZSBBcyDjgafkv53lrZjjgafjgY3jgovjgajmgJ3jgYTjgb7jgZnjgILjg5bjg6njgqbjgrbjg7zjgavjgojjgaPjgabku5Xmp5jjgYznlbDjgarjgorjgb7jgZnjgYvjgonjgIHpganliIfjgarmlrnms5XjgpLpgbjjgpPjgafjgY/jgaDjgZXjgYTjgIIKCi0gICA8aHR0cHM6Ly9kcy1zbC5naXRodWIuaW8vaW50cm8yci9STm90ZWJvb2stSi5uYi5odG1sPgotICAgPGh0dHBzOi8vZHMtc2wuZ2l0aHViLmlvL2ludHJvMnIvUm1hcmtkb3duLUoubmIuaHRtbD4KCldpbmRvd3Mg44Gn44KC44CBTWFjIOOBp+OCguaPkOS+m+OBleOCjOOBpuOBhOOCi+OAgUdvb2dsZSBDaHJvbWUg44Gu5aC05ZCI44Gr44Gv44CBQ29kZSDjg5zjgr/jg7PjgYvjgonjgIHjg4Djg7Pjg63jg7zjg4njgZXjgozjgovjga/jgZrjgafjgZnjgIIKCiMjIOOCr+ODqeOCpuODiSAtIFBvc2l0IENsb3VkCgpSU3R1ZGlvIENsb3Vk44Gv44CB6Kqw44Gn44KC44Kq44Oz44Op44Kk44Oz44Gn44OH44O844K/44K144Kk44Ko44Oz44K544KS6KGM44GE44CB5YWx5pyJ44GX44CB5pWZ44GI44CB5a2m44G244GT44Go44GM44Gn44GN44KL44CB6Lu96YeP44Gn44Kv44Op44Km44OJ44OZ44O844K544Gu44K944Oq44Ol44O844K344On44Oz44Gn44GZ44CCCgojIyMg44Kv44Op44Km44OJ44K144O844OT44K544CASG93IHRvIFN0YXJ0IFBvc2l0IENsb3VkCgoxLiAgR28gdG8gPGh0dHBzOi8vcG9zaXQuY2xvdWQvPgoyLiAgU2lnbiBVcDogdG9wIHJpZ2h0CjMuICBFbWFpbCBhZGRyZXNzIG9yIEdvb2dsZSBhY2NvdW50CjQuICBOZXcgUHJvamVjdDogUHJvamVjdCBOYW1lCgojIyDnt7Tnv5LllY/poYwgUG9zaXQgUHJpbWVycwoKUG9zaXQgUHJpbWVycyA8aHR0cHM6Ly9wb3NpdC5jbG91ZC9sZWFybi9wcmltZXJzPgoKIyMjIOacgOWIneOBrua8lOe/kuOAgFRoZSBCYXNpY3MgLS0gcjRkczogRXhwbG9yZSwgSQoKLSAgIFtWaXN1YWxpemF0aW9uIEJhc2ljc10oaHR0cHM6Ly9yc3R1ZGlvLmNsb3VkL2xlYXJuL3ByaW1lcnMvMS4xKQotICAgW1Byb2dyYW1taW5nIEJhc2ljc10oaHR0cHM6Ly9yc3R1ZGlvLmNsb3VkL2xlYXJuL3ByaW1lcnMvMS4yKQoKIyMgOS4g5Y+C6ICD5paH54yuIFJlZmVyZW5jZXMKCi0gICBSIEZvciBEYXRhIFNjaWVuY2UsIGJ5IEguIFdpY2toYW06IDxodHRwczovL3I0ZHMuaGFkLmNvLm56PgoKICAgIC0gICBJbnRyb2R1Y3Rpb246IDxodHRwczovL3I0ZHMuaGFkLmNvLm56L2V4cGxvcmUtaW50cm8uaHRtbCNleHBsb3JlLWludHJvPgoKLSAgIEJvb2tkb3duOiA8aHR0cHM6Ly9ib29rZG93bi5vcmc+LCBbQXJjaGl2ZV0oaHR0cHM6Ly9ib29rZG93bi5vcmcvaG9tZS9hcmNoaXZlLykKCi0gICBbR2V0IFN0YXJ0ZWQ6IFIgU3R1ZGlvIOOBpyBSIOOCkuOBr+OBmOOCgeOCiOOBhuOAgVIgTWFya2Rvd25dKGh0dHBzOi8vZHMtc2wuZ2l0aHViLmlvL2ludHJvMnIvZ2V0c3RhcnRlZC5odG1sKQoKLSAgIFtJbnRyb2R1Y3RvbiB0byBSXShodHRwczovL2RzLXNsLmdpdGh1Yi5pby9pbnRybzJyL2ludHJvMnIubmIuaHRtbCMzX0RhdGFfQW5hbHlzaXNfVXNpbmdfUlN0dWRpbykKCi0gICBbRGF0YSBBbmFseXNpcyBmb3IgUmVzZWFyY2hlcnMgMjAyMl0oaHR0cHM6Ly9pY3UtaHN1enVraS5naXRodWIuaW8vZGE0cjIwMjIvKQoKIyBSIE1hcmtkb3duCgojIyDmnIDliJ3jga7kuIDmrakgTGV0J3MgZ2V0IHN0YXJ0ZWQhCgoxLiAg5rqW5YKZ77ya44OR44OD44Kx44O844K444Gu44Kk44Oz44K544OI44O844OrCjIuICBSIE5vdGVib29rCjMuICDml6XmnKzoqp7jga7jg4bjg7Pjg5fjg6zjg7zjg4gKNC4gIFIgTWFya2Rvd24g44GE44GP44Gk44GL44GuIE91dHB1dAo1LiAgUiBTY3JpcHQg5a6f6KGM6KiY6YyyCjYuICDjg5Hjg4PjgrHjg7zjgrggLSBQYWNrYWdlcwoKIyMgMi4gUiBOb3RlYm9vawoKUiBNYXJrZG93buOBr+ODh+ODvOOCv+OCteOCpOOCqOODs+OCueOBruOBn+OCgeOBruOCquODvOOCteODquODs+OCsOODleODrOODvOODoOODr+ODvOOCr+OAggoK44Kz44O844OJ77yI44OX44Ot44Kw44Op44Og77yJ44Go44Gd44Gu5a6f6KGM57WQ5p6c44CB44KS6KiY6Yyy44O76KGo56S644GX44CB6auY5ZOB6LOq44Gu44Os44Od44O844OI44Gu5L2c5oiQ44KS5Y+v6IO944Gr44GX44G+44GZ44CCCgpSIE5vdGVib29rIOOBr+OAgeeLrOeri+OBl+OBpuOCpOODs+OCv+ODqeOCr+ODhuOCo+ODluOBq+Wun+ihjOOBp+OBjeOCi+ODgeODo+ODs+OCr+OCkuaMgeOBpFIgTWFya2Rvd27jg4njgq3jg6Xjg6Hjg7Pjg4jjga7kuIDjgaTjga7lvaLlvI/jgafjgIHlhaXlipvjga7jgZnjgZDkuIvjgavlh7rlipvjgYzooajnpLrjgZnjgovjgZPjgajjgYzjgafjgY3jgb7jgZnjgIIKCjEuICBGaWxlIFw+IE5ldyBGaWxlIFw+IFIgTm90ZWJvb2sKMi4gIFNhdmUgd2l0aCBhIGZpbGUgbmFtZSwgc2F5LCB0ZXN0LW5vdGVib29rCjMuICBQcmV2aWV3IGJ5IFtQcmV2aWV3XSBidXR0b24KNC4gIFJ1biBDb2RlIENodW5rIHBsb3QoY2FycykgYW5kIHRoZW4gUHJldmlldyBhZ2Fpbi4KCiMjIDMuIOaXpeacrOiqnuOBruODhuODs+ODl+ODrOODvOODiAoK5LiL44Gu44Oq44Oz44Kv44KS6ZaL44GN44CB5Y+z5LiK44GuIENvZGUg44Oc44K/44Oz44GL44KJ44CBRG93bmxvYWQgUm1kIOOCkumBuOaKnuOBmeOCi+OBqOOAgeODgOOCpuODs+ODreODvOODieOBp+OBjeOBvuOBmeOBi+OCieOAgeODgOOCpOODs+ODreODvOODieOBl+OBn+OCguOBruOCkuOAgeODl+ODreOCuOOCp+OCr+ODiOODu+ODleOCqeODvOODq+ODgOODvOOBq+enu+WLleOBvuOBn+OBr+OCs+ODlOODvOOBl+OBpuOBj+OBoOOBleOBhOOAguODgOOCpuODs+ODreODvOODieOBp+OBjeOBquOBhOOBqOOBjeOBr+OAgUN0cmwg44KS5oq844GX44Gq44GM44KJ44CBRG93bmxvYWQgUm1kIOOCkuOCr+ODquODg+OCr+OBmeOCi+OBqOOAgVNhdmUgQXMg44Gn5L+d5a2Y44Gn44GN44KL44Go5oCd44GE44G+44GZ44CC44OW44Op44Km44K244O844Gr44KI44Gj44Gm5LuV5qeY44GM55Ww44Gq44KK44G+44GZ44GL44KJ44CB6YGp5YiH44Gq5pa55rOV44KS6YG444KT44Gn44GP44Gg44GV44GE44CCCgotICAgPGh0dHBzOi8vZHMtc2wuZ2l0aHViLmlvL2ludHJvMnIvUk5vdGVib29rLUoubmIuaHRtbD4KLSAgIDxodHRwczovL2RzLXNsLmdpdGh1Yi5pby9pbnRybzJyL1JtYXJrZG93bi1KLm5iLmh0bWw+CgpXaW5kb3dzIOOBp+OCguOAgU1hYyDjgafjgoLmj5DkvpvjgZXjgozjgabjgYTjgovjgIFHb29nbGUgQ2hyb21lIOOBruWgtOWQiOOBq+OBr+OAgUNvZGUg44Oc44K/44Oz44GL44KJ44CB44OA44Oz44Ot44O844OJ44GV44KM44KL44Gv44Ga44Gn44GZ44CCCgo=